From 8abcaeee6fc59a9f89430f32a9a26e6f4bb4c76c Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 11:03:21 +0300 Subject: [PATCH 1/4] vm: restrict max size in NEWARRAY/NEWSTRUCT --- pkg/vm/vm.go | 14 ++++++++++---- pkg/vm/vm_test.go | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 2f06bc8b0..7bc88723c 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -753,8 +753,11 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { case *ArrayItem: v.estack.PushVal(t) default: - n := item.BigInt() - items := makeArrayOfFalses(int(n.Int64())) + n := item.BigInt().Int64() + if n > MaxArraySize { + panic("too long array") + } + items := makeArrayOfFalses(int(n)) v.estack.PushVal(&ArrayItem{items}) } @@ -766,8 +769,11 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { case *StructItem: v.estack.PushVal(t) default: - n := item.BigInt() - items := makeArrayOfFalses(int(n.Int64())) + n := item.BigInt().Int64() + if n > MaxArraySize { + panic("too long struct") + } + items := makeArrayOfFalses(int(n)) v.estack.PushVal(&StructItem{items}) } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index e14f08dad..4cd5a0d60 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -538,6 +538,14 @@ func TestNEWARRAYByteArray(t *testing.T) { assert.Equal(t, &ArrayItem{[]StackItem{}}, vm.estack.Pop().value) } +func TestNEWARRAYBadSize(t *testing.T) { + prog := makeProgram(NEWARRAY) + vm := load(prog) + vm.estack.PushVal(MaxArraySize + 1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + func TestNEWSTRUCTInteger(t *testing.T) { prog := makeProgram(NEWSTRUCT) vm := load(prog) @@ -580,6 +588,14 @@ func TestNEWSTRUCTByteArray(t *testing.T) { assert.Equal(t, &StructItem{[]StackItem{}}, vm.estack.Pop().value) } +func TestNEWSTRUCTBadSize(t *testing.T) { + prog := makeProgram(NEWSTRUCT) + vm := load(prog) + vm.estack.PushVal(MaxArraySize + 1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + func TestAPPENDArray(t *testing.T) { prog := makeProgram(DUP, PUSH5, APPEND) vm := load(prog) From 2d56c66bdeab2f9aa312d6d3308d29ef726a5cb8 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 11:03:35 +0300 Subject: [PATCH 2/4] vm: restrict max size in APPEND --- pkg/vm/vm.go | 6 ++++++ pkg/vm/vm_test.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 7bc88723c..6c7049700 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -786,10 +786,16 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { switch t := arrElem.value.(type) { case *ArrayItem: arr := t.Value().([]StackItem) + if len(arr) >= MaxArraySize { + panic("too long array") + } arr = append(arr, val) t.value = arr case *StructItem: arr := t.Value().([]StackItem) + if len(arr) >= MaxArraySize { + panic("too long struct") + } arr = append(arr, val) t.value = arr default: diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 4cd5a0d60..98142bc36 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -652,6 +652,24 @@ func TestAPPENDWrongType(t *testing.T) { assert.Equal(t, true, vm.HasFailed()) } +func TestAPPENDGoodSizeLimit(t *testing.T) { + prog := makeProgram(NEWARRAY, DUP, PUSH0, APPEND) + vm := load(prog) + vm.estack.PushVal(MaxArraySize - 1) + vm.Run() + assert.Equal(t, false, vm.state.HasFlag(faultState)) + assert.Equal(t, 1, vm.estack.Len()) + assert.Equal(t, MaxArraySize, len(vm.estack.Pop().Array())) +} + +func TestAPPENDBadSizeLimit(t *testing.T) { + prog := makeProgram(NEWARRAY, DUP, PUSH0, APPEND) + vm := load(prog) + vm.estack.PushVal(MaxArraySize) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + func TestPICKITEMBadIndex(t *testing.T) { prog := makeProgram(PICKITEM) vm := load(prog) From 6f1f9e56bbc7832e0c4db9d5ccaf5182c4002a0f Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 11:07:44 +0300 Subject: [PATCH 3/4] vm: restrict max size in PACK --- pkg/vm/vm.go | 2 +- pkg/vm/vm_test.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 6c7049700..27614ea9f 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -804,7 +804,7 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { case PACK: n := int(v.estack.Pop().BigInt().Int64()) - if n < 0 || n > v.estack.Len() { + if n < 0 || n > v.estack.Len() || n > MaxArraySize { panic("OPACK: invalid length") } diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 98142bc36..8cfc83505 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1604,6 +1604,17 @@ func TestPACKBadLen(t *testing.T) { assert.Equal(t, true, vm.HasFailed()) } +func TestPACKBigLen(t *testing.T) { + prog := makeProgram(PACK) + vm := load(prog) + for i := 0; i <= MaxArraySize; i++ { + vm.estack.PushVal(0) + } + vm.estack.PushVal(MaxArraySize + 1) + vm.Run() + assert.Equal(t, true, vm.HasFailed()) +} + func TestPACKGoodZeroLen(t *testing.T) { prog := makeProgram(PACK) vm := load(prog) From 6d7016c3b9d0c16acdceb951b9809dbb0a9e6471 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 11:18:15 +0300 Subject: [PATCH 4/4] vm: restrict max size in SETITEM --- pkg/vm/vm.go | 3 +++ pkg/vm/vm_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 27614ea9f..c914fd829 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -871,6 +871,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { } arr[index] = item case *MapItem: + if !t.Has(key.value) && len(t.value) >= MaxArraySize { + panic("too big map") + } t.Add(key.value, item) default: diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 8cfc83505..d2f09923e 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -734,6 +734,38 @@ func TestSETITEMMap(t *testing.T) { assert.Equal(t, makeStackItem([]byte{0, 1}), vm.estack.Pop().value) } +func TestSETITEMBigMapBad(t *testing.T) { + prog := makeProgram(SETITEM) + vm := load(prog) + + m := NewMapItem() + for i := 0; i < MaxArraySize; i++ { + m.Add(makeStackItem(i), makeStackItem(i)) + } + vm.estack.Push(&Element{value: m}) + vm.estack.PushVal(MaxArraySize) + vm.estack.PushVal(0) + + vm.Run() + assert.Equal(t, true, vm.HasFailed()) +} + +func TestSETITEMBigMapGood(t *testing.T) { + prog := makeProgram(SETITEM) + vm := load(prog) + + m := NewMapItem() + for i := 0; i < MaxArraySize; i++ { + m.Add(makeStackItem(i), makeStackItem(i)) + } + vm.estack.Push(&Element{value: m}) + vm.estack.PushVal(0) + vm.estack.PushVal(0) + + vm.Run() + assert.Equal(t, false, vm.HasFailed()) +} + func TestSIZENoArgument(t *testing.T) { prog := makeProgram(SIZE) vm := load(prog)