diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index afddd8bff..3872be99b 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -716,6 +716,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { // For now we will assume that there are only byte slice conversions. // E.g. []byte("foobar") or []byte(scriptHash). ast.Walk(c, n.Args[0]) + c.emitConvert(vm.BufferT) return nil } @@ -1096,7 +1097,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { case "ToBool": typ = vm.BooleanT } - emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)}) + c.emitConvert(typ) case "SHA256": emit.Syscall(c.prog.BinWriter, "Neo.Crypto.SHA256") case "AppCall": @@ -1121,6 +1122,7 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) { } bytes := uint160.BytesBE() emit.Bytes(c.prog.BinWriter, bytes) + c.emitConvert(vm.BufferT) } } @@ -1146,6 +1148,11 @@ func transformArgs(fun ast.Expr, args []ast.Expr) []ast.Expr { return args } +// emitConvert converts top stack item to the specified type. +func (c *codegen) emitConvert(typ vm.StackItemType) { + emit.Instruction(c.prog.BinWriter, opcode.CONVERT, []byte{byte(typ)}) +} + func (c *codegen) convertByteArray(lit *ast.CompositeLit) { buf := make([]byte, len(lit.Elts)) for i := 0; i < len(lit.Elts); i++ { @@ -1154,6 +1161,7 @@ func (c *codegen) convertByteArray(lit *ast.CompositeLit) { buf[i] = byte(val) } emit.Bytes(c.prog.BinWriter, buf) + c.emitConvert(vm.BufferT) } func (c *codegen) convertMap(lit *ast.CompositeLit) { diff --git a/pkg/compiler/convert_test.go b/pkg/compiler/convert_test.go index 0bcd8eace..379d7ce39 100644 --- a/pkg/compiler/convert_test.go +++ b/pkg/compiler/convert_test.go @@ -38,7 +38,8 @@ func TestConvert(t *testing.T) { {"bool", "12", true}, {"bool", "0", false}, {"bool", "[]byte{0, 1, 0}", true}, - {"bool", "[]byte{0}", false}, + {"bool", "[]byte{0}", true}, + {"bool", `""`, false}, {"int64", "true", big.NewInt(1)}, {"int64", "false", big.NewInt(0)}, {"int64", "12", big.NewInt(12)}, diff --git a/pkg/compiler/slice_test.go b/pkg/compiler/slice_test.go index 629b1b52d..d6829925b 100644 --- a/pkg/compiler/slice_test.go +++ b/pkg/compiler/slice_test.go @@ -180,6 +180,27 @@ var sliceTestCases = []testCase{ vm.NewByteArrayItem([]byte("b")), }, }, + { + "byte-slice assignment", + `package foo + func Main() []byte { + a := []byte{0, 1, 2} + a[1] = 42 + return a + }`, + []byte{0, 42, 2}, + }, + { + "byte-slice assignment after string conversion", + `package foo + func Main() []byte { + a := "abc" + b := []byte(a) + b[1] = 42 + return []byte(a) + }`, + []byte{0x61, 0x62, 0x63}, + }, } func TestSliceOperations(t *testing.T) {