From 17f3a21e271b52933ea8de0eb915a04e56a08a11 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Wed, 11 Sep 2019 12:00:11 +0300 Subject: [PATCH] vm: harden SUBSTR implementation against bad index/offset values The upper index bound for slices is capacity, not length. Check for negative values also. Fixes #387. --- pkg/vm/vm.go | 9 +++++++++ pkg/vm/vm_test.go | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index e5c909508..e20f0cedd 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -320,6 +320,15 @@ func (v *VM) execute(ctx *Context, op Instruction) { l := int(v.estack.Pop().BigInt().Int64()) o := int(v.estack.Pop().BigInt().Int64()) s := v.estack.Pop().Bytes() + if l < 0 { + panic("negative length") + } + if o < 0 { + panic("negative index") + } + if l+o > len(s) { + panic("out of bounds access") + } v.estack.PushVal(s[o : o+l]) case LEFT: l := int(v.estack.Pop().BigInt().Int64()) diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index dfb4a5d30..ed36f27fd 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -878,6 +878,38 @@ func TestSUBSTRBadLen(t *testing.T) { assert.Equal(t, true, vm.state.HasFlag(faultState)) } +func TestSUBSTRBad387(t *testing.T) { + prog := makeProgram(SUBSTR) + vm := load(prog) + b := make([]byte, 6, 20) + copy(b, "abcdef") + vm.estack.PushVal(b) + vm.estack.PushVal(1) + vm.estack.PushVal(6) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestSUBSTRBadNegativeOffset(t *testing.T) { + prog := makeProgram(SUBSTR) + vm := load(prog) + vm.estack.PushVal([]byte("abcdef")) + vm.estack.PushVal(-1) + vm.estack.PushVal(3) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + +func TestSUBSTRBadNegativeLen(t *testing.T) { + prog := makeProgram(SUBSTR) + vm := load(prog) + vm.estack.PushVal([]byte("abcdef")) + vm.estack.PushVal(3) + vm.estack.PushVal(-1) + vm.Run() + assert.Equal(t, true, vm.state.HasFlag(faultState)) +} + func TestLEFTBadNoArgs(t *testing.T) { prog := makeProgram(LEFT) vm := load(prog)