compiler: rewrite jump targets properly

Old implementation could view 0x62 byte in
a script as a JMP instruction irregardless of whether it is
a real opcode or a part of a parameter of another instruction.
In this commit instructions are decoded together with parameters
during jump label rewriting.
This commit is contained in:
Evgenii Stratonikov 2020-02-03 12:10:07 +03:00
parent cc9ace6426
commit 3e84f2bdf8
3 changed files with 26 additions and 6 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/CityOfZion/neo-go/pkg/encoding/address"
"github.com/CityOfZion/neo-go/pkg/io"
"github.com/CityOfZion/neo-go/pkg/vm"
"github.com/CityOfZion/neo-go/pkg/vm/emit"
"github.com/CityOfZion/neo-go/pkg/vm/opcode"
)
@ -1045,16 +1046,19 @@ func (c *codegen) resolveFuncDecls(f *ast.File) {
}
func (c *codegen) writeJumps(b []byte) {
for i, op := range b {
j := i + 1
switch opcode.Opcode(op) {
ctx := vm.NewContext(b)
for op, _, err := ctx.Next(); err == nil && ctx.NextIP() < len(b); op, _, err = ctx.Next() {
switch op {
case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL:
index := int16(binary.LittleEndian.Uint16(b[j : j+2]))
// we can't use arg returned by ctx.Next() because it is copied
arg := b[ctx.NextIP()-2:]
index := int16(binary.LittleEndian.Uint16(arg))
if int(index) > len(c.l) || int(index) < 0 {
continue
}
offset := uint16(c.l[index] - i)
binary.LittleEndian.PutUint16(b[j:j+2], offset)
offset := uint16(c.l[index] - ctx.NextIP() + 3)
binary.LittleEndian.PutUint16(arg, offset)
}
}
}