Merge pull request #643 from nspcc-dev/fix/jump

compiler: rewrite jump targets properly

Closes #630.
This commit is contained in:
Roman Khimov 2020-02-12 12:05:35 +03:00 committed by GitHub
commit bcff9faac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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/encoding/address"
"github.com/CityOfZion/neo-go/pkg/io" "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/emit"
"github.com/CityOfZion/neo-go/pkg/vm/opcode" "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) { func (c *codegen) writeJumps(b []byte) {
for i, op := range b { ctx := vm.NewContext(b)
j := i + 1 for op, _, err := ctx.Next(); err == nil && ctx.NextIP() < len(b); op, _, err = ctx.Next() {
switch opcode.Opcode(op) { switch op {
case opcode.JMP, opcode.JMPIFNOT, opcode.JMPIF, opcode.CALL: 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 { if int(index) > len(c.l) || int(index) < 0 {
continue continue
} }
offset := uint16(c.l[index] - i) offset := uint16(c.l[index] - ctx.NextIP() + 3)
binary.LittleEndian.PutUint16(b[j:j+2], offset) binary.LittleEndian.PutUint16(arg, offset)
} }
} }
} }

View file

@ -74,3 +74,14 @@ var sliceTestCases = []testCase{
func TestSliceOperations(t *testing.T) { func TestSliceOperations(t *testing.T) {
runTestCases(t, sliceTestCases) runTestCases(t, sliceTestCases)
} }
func TestJumps(t *testing.T) {
src := `
package foo
func Main() []byte {
buf := []byte{0x62, 0x01, 0x00}
return buf
}
`
eval(t, src, []byte{0x62, 0x01, 0x00})
}

View file

@ -47,6 +47,11 @@ func NewContext(b []byte) *Context {
} }
} }
// NextIP returns next instruction pointer.
func (c *Context) NextIP() int {
return c.nextip
}
// Next returns the next instruction to execute with its parameter if any. After // Next returns the next instruction to execute with its parameter if any. After
// its invocation the instruction pointer points to the instruction being // its invocation the instruction pointer points to the instruction being
// returned. // returned.