Merge pull request #435 from nspcc-dev/fix/max_item_size

Restrict max item size on stack in CAT and PUSHDATA4, one more step towards #373.
This commit is contained in:
Roman Khimov 2019-10-17 20:06:13 +03:00 committed by GitHub
commit d46d679f36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 32 additions and 2 deletions

View file

@ -59,6 +59,9 @@ func (c *Context) Next() (Instruction, []byte, error) {
case PUSHDATA4: case PUSHDATA4:
var n uint32 var n uint32
r.ReadLE(&n) r.ReadLE(&n)
if n > MaxItemSize {
return instr, nil, errors.New("parameter is too big")
}
numtoread = int(n) numtoread = int(n)
c.nextip += 4 c.nextip += 4
case JMP, JMPIF, JMPIFNOT, CALL: case JMP, JMPIF, JMPIFNOT, CALL:

View file

@ -28,6 +28,10 @@ var (
const ( const (
// MaxArraySize is the maximum array size allowed in the VM. // MaxArraySize is the maximum array size allowed in the VM.
MaxArraySize = 1024 MaxArraySize = 1024
// MaxItemSize is the maximum item size allowed in the VM.
MaxItemSize = 1024 * 1024
maxSHLArg = 256 maxSHLArg = 256
minSHLArg = -256 minSHLArg = -256
) )
@ -439,6 +443,9 @@ func (v *VM) execute(ctx *Context, op Instruction, parameter []byte) {
case CAT: case CAT:
b := v.estack.Pop().Bytes() b := v.estack.Pop().Bytes()
a := 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...) ab := append(a, b...)
v.estack.PushVal(ab) v.estack.PushVal(ab)
case SUBSTR: case SUBSTR:

View file

@ -2,6 +2,7 @@ package vm
import ( import (
"bytes" "bytes"
"encoding/binary"
"encoding/hex" "encoding/hex"
"math/big" "math/big"
"math/rand" "math/rand"
@ -175,6 +176,16 @@ func TestPushData4ShortN(t *testing.T) {
assert.Equal(t, true, vm.HasFailed()) 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) { func TestPushData4Good(t *testing.T) {
prog := makeProgram(PUSHDATA4, 3, 0, 0, 0, 1, 2, 3) prog := makeProgram(PUSHDATA4, 3, 0, 0, 0, 1, 2, 3)
vm := load(prog) vm := load(prog)
@ -1413,6 +1424,15 @@ func TestCATBadOneArg(t *testing.T) {
assert.Equal(t, true, vm.HasFailed()) 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) { func TestCATGood(t *testing.T) {
prog := makeProgram(CAT) prog := makeProgram(CAT)
vm := load(prog) vm := load(prog)