diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index 57f2db7ba..d39549d6f 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -301,7 +301,12 @@ func (c *codegen) analyzeFuncUsage() funcUsage { } usage[name] = true - old := c.importMap + pkg := c.mainPkg + if fd.path != "" { + pkg = c.buildInfo.program.Package(fd.path) + } + c.typeInfo = &pkg.Info + c.currPkg = pkg.Pkg c.importMap = fd.importMap ast.Inspect(fd.decl, func(node ast.Node) bool { switch n := node.(type) { @@ -316,7 +321,6 @@ func (c *codegen) analyzeFuncUsage() funcUsage { } return true }) - c.importMap = old } diff = nextDiff } diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 1fefc5e51..cdc36f0aa 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -16,6 +16,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/util" + "github.com/nspcc-dev/neo-go/pkg/util/bitfield" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -2073,7 +2074,13 @@ func CodeGen(info *buildInfo) ([]byte, *DebugInfo, error) { if err != nil { return nil, nil, err } - return buf, c.emitDebugInfo(buf), nil + + methods := bitfield.New(len(buf)) + di := c.emitDebugInfo(buf) + for i := range di.Methods { + methods.Set(int(di.Methods[i].Range.Start)) + } + return buf, di, vm.IsScriptCorrect(buf, methods) } func (c *codegen) resolveFuncDecls(f *ast.File, pkg *types.Package) { @@ -2168,6 +2175,9 @@ func (c *codegen) replaceLabelWithOffset(ip int, arg []byte) (int, error) { if int(index) > len(c.l) { return 0, fmt.Errorf("unexpected label number: %d (max %d)", index, len(c.l)) } + if c.l[index] < 0 { + return 0, fmt.Errorf("invalid label target: %d at %d", c.l[index], ip) + } offset := c.l[index] - ip if offset > math.MaxInt32 || offset < math.MinInt32 { return 0, fmt.Errorf("label offset is too big at the instruction %d: %d (max %d, min %d)", diff --git a/pkg/compiler/function_call_test.go b/pkg/compiler/function_call_test.go index a256eb47c..9503f59ba 100644 --- a/pkg/compiler/function_call_test.go +++ b/pkg/compiler/function_call_test.go @@ -350,4 +350,17 @@ func TestUnusedFunctions(t *testing.T) { require.NoError(t, err) eval(t, src, big.NewInt(65)) }) + t.Run("method inside of an imported package", func(t *testing.T) { + // Check that import map is set correctly during package traversal. + src := `package foo + import inner "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/nestedcall" + func Main() int { + var t inner.Token + return t.Method() + }` + + _, err := compiler.Compile("foo", strings.NewReader(src)) + require.NoError(t, err) + eval(t, src, big.NewInt(2231)) + }) } diff --git a/pkg/compiler/testdata/nestedcall/call.go b/pkg/compiler/testdata/nestedcall/call.go index bd05c6f21..4d306bc7b 100644 --- a/pkg/compiler/testdata/nestedcall/call.go +++ b/pkg/compiler/testdata/nestedcall/call.go @@ -28,3 +28,16 @@ func y() int { tmp := 10 return tmp } + +// Token is stateless token. +type Token struct{} + +// Method is a method. +func (t Token) Method() int { + return t.Inner() +} + +// Inner is a function to be called in Method. +func (t Token) Inner() int { + return 2231 +}