From cae431b844dcd0c935eee79089d662702a551311 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 17:01:03 +0300 Subject: [PATCH 1/2] vm: restrict max item size in CAT --- pkg/vm/vm.go | 11 +++++++++-- pkg/vm/vm_test.go | 9 +++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index c914fd829..8671d5acb 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -28,8 +28,12 @@ var ( const ( // MaxArraySize is the maximum array size allowed in the VM. MaxArraySize = 1024 - maxSHLArg = 256 - minSHLArg = -256 + + // MaxItemSize is the maximum item size allowed in the VM. + MaxItemSize = 1024 * 1024 + + maxSHLArg = 256 + minSHLArg = -256 ) // VM represents the virtual machine. @@ -439,6 +443,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) { case CAT: b := v.estack.Pop().Bytes() a := v.estack.Pop().Bytes() + if l := len(a) + len(b); l > MaxItemSize { + panic(fmt.Sprintf("too big item: %d", l)) + } ab := append(a, b...) v.estack.PushVal(ab) case SUBSTR: diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index d2f09923e..dea4a421f 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1413,6 +1413,15 @@ func TestCATBadOneArg(t *testing.T) { assert.Equal(t, true, vm.HasFailed()) } +func TestCATBadBigItem(t *testing.T) { + prog := makeProgram(CAT) + vm := load(prog) + vm.estack.PushVal(make([]byte, MaxItemSize/2+1)) + vm.estack.PushVal(make([]byte, MaxItemSize/2+1)) + vm.Run() + assert.Equal(t, true, vm.HasFailed()) +} + func TestCATGood(t *testing.T) { prog := makeProgram(CAT) vm := load(prog) From 487570153b15f086f87dcc942fe0e26f9cd8a6a5 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Thu, 17 Oct 2019 17:10:00 +0300 Subject: [PATCH 2/2] vm: restrict max item size in PUSHDATA4 --- pkg/vm/context.go | 3 +++ pkg/vm/vm_test.go | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/pkg/vm/context.go b/pkg/vm/context.go index 1e7ac9d1a..67dc7f1fb 100644 --- a/pkg/vm/context.go +++ b/pkg/vm/context.go @@ -59,6 +59,9 @@ func (c *Context) Next() (Instruction, []byte, error) { case PUSHDATA4: var n uint32 r.ReadLE(&n) + if n > MaxItemSize { + return instr, nil, errors.New("parameter is too big") + } numtoread = int(n) c.nextip += 4 case JMP, JMPIF, JMPIFNOT, CALL: diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index dea4a421f..7b870a733 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -2,6 +2,7 @@ package vm import ( "bytes" + "encoding/binary" "encoding/hex" "math/big" "math/rand" @@ -175,6 +176,16 @@ func TestPushData4ShortN(t *testing.T) { assert.Equal(t, true, vm.HasFailed()) } +func TestPushData4BigN(t *testing.T) { + prog := make([]byte, 1+4+MaxItemSize+1) + prog[0] = byte(PUSHDATA4) + binary.LittleEndian.PutUint32(prog[1:], MaxItemSize+1) + + vm := load(prog) + vm.Run() + assert.Equal(t, true, vm.HasFailed()) +} + func TestPushData4Good(t *testing.T) { prog := makeProgram(PUSHDATA4, 3, 0, 0, 0, 1, 2, 3) vm := load(prog)