diff --git a/pkg/vm/opcode/opcode.go b/pkg/vm/opcode/opcode.go index 9afaf8af9..b729c1e16 100644 --- a/pkg/vm/opcode/opcode.go +++ b/pkg/vm/opcode/opcode.go @@ -147,6 +147,7 @@ const ( // Splice NEWBUFFER Opcode = 0x88 + MEMCPY Opcode = 0x89 CAT Opcode = 0x8B SUBSTR Opcode = 0x8C LEFT Opcode = 0x8D diff --git a/pkg/vm/opcode/opcode_string.go b/pkg/vm/opcode/opcode_string.go index 3cc0757f4..8545c39f4 100644 --- a/pkg/vm/opcode/opcode_string.go +++ b/pkg/vm/opcode/opcode_string.go @@ -133,6 +133,7 @@ func _() { _ = x[STARG6-134] _ = x[STARG-135] _ = x[NEWBUFFER-136] + _ = x[MEMCPY-137] _ = x[CAT-139] _ = x[SUBSTR-140] _ = x[LEFT-141] @@ -191,7 +192,7 @@ func _() { _ = x[CONVERT-219] } -const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLCALLAABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT" +const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHAPUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLCALLAABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENINITSSLOTINITSLOTLDSFLD0LDSFLD1LDSFLD2LDSFLD3LDSFLD4LDSFLD5LDSFLD6LDSFLDSTSFLD0STSFLD1STSFLD2STSFLD3STSFLD4STSFLD5STSFLD6STSFLDLDLOC0LDLOC1LDLOC2LDLOC3LDLOC4LDLOC5LDLOC6LDLOCSTLOC0STLOC1STLOC2STLOC3STLOC4STLOC5STLOC6STLOCLDARG0LDARG1LDARG2LDARG3LDARG4LDARG5LDARG6LDARGSTARG0STARG1STARG2STARG3STARG4STARG5STARG6STARGNEWBUFFERMEMCPYCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT" var _Opcode_map = map[Opcode]string{ 0: _Opcode_name[0:8], @@ -316,62 +317,63 @@ var _Opcode_map = map[Opcode]string{ 134: _Opcode_name[718:724], 135: _Opcode_name[724:729], 136: _Opcode_name[729:738], - 139: _Opcode_name[738:741], - 140: _Opcode_name[741:747], - 141: _Opcode_name[747:751], - 142: _Opcode_name[751:756], - 144: _Opcode_name[756:762], - 145: _Opcode_name[762:765], - 146: _Opcode_name[765:767], - 147: _Opcode_name[767:770], - 151: _Opcode_name[770:775], - 152: _Opcode_name[775:783], - 153: _Opcode_name[783:787], - 154: _Opcode_name[787:790], - 155: _Opcode_name[790:796], - 156: _Opcode_name[796:799], - 157: _Opcode_name[799:802], - 158: _Opcode_name[802:805], - 159: _Opcode_name[805:808], - 160: _Opcode_name[808:811], - 161: _Opcode_name[811:814], - 162: _Opcode_name[814:817], - 168: _Opcode_name[817:820], - 169: _Opcode_name[820:823], - 170: _Opcode_name[823:826], - 171: _Opcode_name[826:833], - 172: _Opcode_name[833:839], - 177: _Opcode_name[839:841], - 179: _Opcode_name[841:849], - 180: _Opcode_name[849:860], - 181: _Opcode_name[860:862], - 182: _Opcode_name[862:865], - 183: _Opcode_name[865:867], - 184: _Opcode_name[867:870], - 185: _Opcode_name[870:873], - 186: _Opcode_name[873:876], - 187: _Opcode_name[876:882], - 192: _Opcode_name[882:886], - 193: _Opcode_name[886:892], - 194: _Opcode_name[892:901], - 195: _Opcode_name[901:909], - 196: _Opcode_name[909:918], - 197: _Opcode_name[918:928], - 198: _Opcode_name[928:937], - 200: _Opcode_name[937:943], - 202: _Opcode_name[943:947], - 203: _Opcode_name[947:953], - 204: _Opcode_name[953:957], - 205: _Opcode_name[957:963], - 206: _Opcode_name[963:971], - 207: _Opcode_name[971:977], - 208: _Opcode_name[977:984], - 209: _Opcode_name[984:996], - 210: _Opcode_name[996:1002], - 211: _Opcode_name[1002:1012], - 216: _Opcode_name[1012:1018], - 217: _Opcode_name[1018:1024], - 219: _Opcode_name[1024:1031], + 137: _Opcode_name[738:744], + 139: _Opcode_name[744:747], + 140: _Opcode_name[747:753], + 141: _Opcode_name[753:757], + 142: _Opcode_name[757:762], + 144: _Opcode_name[762:768], + 145: _Opcode_name[768:771], + 146: _Opcode_name[771:773], + 147: _Opcode_name[773:776], + 151: _Opcode_name[776:781], + 152: _Opcode_name[781:789], + 153: _Opcode_name[789:793], + 154: _Opcode_name[793:796], + 155: _Opcode_name[796:802], + 156: _Opcode_name[802:805], + 157: _Opcode_name[805:808], + 158: _Opcode_name[808:811], + 159: _Opcode_name[811:814], + 160: _Opcode_name[814:817], + 161: _Opcode_name[817:820], + 162: _Opcode_name[820:823], + 168: _Opcode_name[823:826], + 169: _Opcode_name[826:829], + 170: _Opcode_name[829:832], + 171: _Opcode_name[832:839], + 172: _Opcode_name[839:845], + 177: _Opcode_name[845:847], + 179: _Opcode_name[847:855], + 180: _Opcode_name[855:866], + 181: _Opcode_name[866:868], + 182: _Opcode_name[868:871], + 183: _Opcode_name[871:873], + 184: _Opcode_name[873:876], + 185: _Opcode_name[876:879], + 186: _Opcode_name[879:882], + 187: _Opcode_name[882:888], + 192: _Opcode_name[888:892], + 193: _Opcode_name[892:898], + 194: _Opcode_name[898:907], + 195: _Opcode_name[907:915], + 196: _Opcode_name[915:924], + 197: _Opcode_name[924:934], + 198: _Opcode_name[934:943], + 200: _Opcode_name[943:949], + 202: _Opcode_name[949:953], + 203: _Opcode_name[953:959], + 204: _Opcode_name[959:963], + 205: _Opcode_name[963:969], + 206: _Opcode_name[969:977], + 207: _Opcode_name[977:983], + 208: _Opcode_name[983:990], + 209: _Opcode_name[990:1002], + 210: _Opcode_name[1002:1008], + 211: _Opcode_name[1008:1018], + 216: _Opcode_name[1018:1024], + 217: _Opcode_name[1024:1030], + 219: _Opcode_name[1030:1037], } func (i Opcode) String() string { diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index 3af2446ec..515008ea1 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -642,6 +642,29 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro } v.estack.PushVal(NewBufferItem(make([]byte, n))) + case opcode.MEMCPY: + n := toInt(v.estack.Pop().BigInt()) + if n < 0 { + panic("invalid size") + } + si := toInt(v.estack.Pop().BigInt()) + if si < 0 { + panic("invalid source index") + } + src := v.estack.Pop().Bytes() + if sum := si + n; sum < 0 || sum > len(src) { + panic("size is too big") + } + di := toInt(v.estack.Pop().BigInt()) + if di < 0 { + panic("invalid destination index") + } + dst := v.estack.Pop().value.(*BufferItem).value + if sum := si + n; sum < 0 || sum > len(dst) { + panic("size is too big") + } + copy(dst[di:], src[si:si+n]) + case opcode.CAT: b := v.estack.Pop().Bytes() a := v.estack.Pop().Bytes() diff --git a/pkg/vm/vm_test.go b/pkg/vm/vm_test.go index 112be1e27..2a906edab 100644 --- a/pkg/vm/vm_test.go +++ b/pkg/vm/vm_test.go @@ -1161,6 +1161,19 @@ func TestNEWBUFFER(t *testing.T) { t.Run("TooBig", getTestFuncForVM(prog, nil, MaxItemSize+1)) } +func TestMEMCPY(t *testing.T) { + prog := makeProgram(opcode.MEMCPY) + t.Run("Good", func(t *testing.T) { + buf := NewBufferItem([]byte{0, 1, 2, 3}) + runWithArgs(t, prog, NewBufferItem([]byte{0, 6, 7, 3}), buf, buf, 1, []byte{4, 5, 6, 7}, 2, 2) + }) + t.Run("NegativeSize", getTestFuncForVM(prog, nil, NewBufferItem([]byte{0, 1}), 0, []byte{2}, 0, -1)) + t.Run("NegativeSrcIndex", getTestFuncForVM(prog, nil, NewBufferItem([]byte{0, 1}), 0, []byte{2}, -1, 1)) + t.Run("NegativeDstIndex", getTestFuncForVM(prog, nil, NewBufferItem([]byte{0, 1}), -1, []byte{2}, 0, 1)) + t.Run("BigSizeSrc", getTestFuncForVM(prog, nil, NewBufferItem([]byte{0, 1}), 0, []byte{2}, 0, 2)) + t.Run("BigSizeDst", getTestFuncForVM(prog, nil, NewBufferItem([]byte{0, 1}), 0, []byte{2, 3, 4}, 0, 3)) +} + func TestNEWARRAY0(t *testing.T) { prog := makeProgram(opcode.NEWARRAY0) runWithArgs(t, prog, []StackItem{})