From eade327b9b290e2f1a99076580f6d2d9a5ba4b19 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Tue, 21 Nov 2023 19:31:31 +0300 Subject: [PATCH] compiler: check for pkg nilness, fix #3202 Unfortunately, when import cycle happens somewhere deep in the import chain we dont't get an error from packages.Load(). But it leaves some imports uninitialized, so at least we can check for them. Signed-off-by: Roman Khimov --- pkg/compiler/analysis.go | 9 +++++- pkg/compiler/codegen.go | 3 ++ pkg/compiler/import_test.go | 28 +++++++++++++++++++ .../testdata/importcycle/pkg1/pkg1.go | 9 ++++++ .../testdata/importcycle/pkg2/pkg2.go | 11 ++++++++ .../testdata/importcycle/pkg3/pkg3.go | 11 ++++++++ 6 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 pkg/compiler/testdata/importcycle/pkg1/pkg1.go create mode 100644 pkg/compiler/testdata/importcycle/pkg2/pkg2.go create mode 100644 pkg/compiler/testdata/importcycle/pkg3/pkg3.go diff --git a/pkg/compiler/analysis.go b/pkg/compiler/analysis.go index b3ca6954a..79827d303 100644 --- a/pkg/compiler/analysis.go +++ b/pkg/compiler/analysis.go @@ -282,7 +282,14 @@ func (c *codegen) visitPkg(pkg *packages.Package, seen map[string]bool) { return } for _, imp := range pkg.Types.Imports() { - c.visitPkg(pkg.Imports[imp.Path()], seen) + var subpkg = pkg.Imports[imp.Path()] + if subpkg == nil { + if c.prog.Err == nil { + c.prog.Err = fmt.Errorf("failed to load %q package from %q, import cycle?", imp.Path(), pkg.PkgPath) + } + return + } + c.visitPkg(subpkg, seen) } seen[pkg.PkgPath] = true c.packages = append(c.packages, pkg.PkgPath) diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 957a508e7..e03866aad 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -2209,6 +2209,9 @@ func (c *codegen) newLambda(u uint16, lit *ast.FuncLit) { func (c *codegen) compile(info *buildInfo, pkg *packages.Package) error { c.mainPkg = pkg c.analyzePkgOrder() + if c.prog.Err != nil { + return c.prog.Err + } c.fillDocumentInfo() funUsage := c.analyzeFuncAndGlobalVarUsage() if c.prog.Err != nil { diff --git a/pkg/compiler/import_test.go b/pkg/compiler/import_test.go index 9080209f4..967d387b1 100644 --- a/pkg/compiler/import_test.go +++ b/pkg/compiler/import_test.go @@ -2,7 +2,11 @@ package compiler_test import ( "math/big" + "strings" "testing" + + "github.com/nspcc-dev/neo-go/pkg/compiler" + "github.com/stretchr/testify/require" ) func TestImportFunction(t *testing.T) { @@ -61,3 +65,27 @@ func TestImportNameSameAsOwn(t *testing.T) { }` eval(t, src, big.NewInt(3)) } + +func TestImportCycleDirect(t *testing.T) { + src := ` + package some + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" + func Main() int { + return pkg2.A + } + ` + _, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil) + require.Error(t, err) +} + +func TestImportCycleIndirect(t *testing.T) { + src := ` + package some + import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg1" + func Main() int { + return pkg1.A + } + ` + _, _, err := compiler.CompileWithOptions("some.go", strings.NewReader(src), nil) + require.Error(t, err) +} diff --git a/pkg/compiler/testdata/importcycle/pkg1/pkg1.go b/pkg/compiler/testdata/importcycle/pkg1/pkg1.go new file mode 100644 index 000000000..63bdc4fb7 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg1/pkg1.go @@ -0,0 +1,9 @@ +package pkg1 + +import "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" + +var A int + +func init() { + pkg2.A = 1 +} diff --git a/pkg/compiler/testdata/importcycle/pkg2/pkg2.go b/pkg/compiler/testdata/importcycle/pkg2/pkg2.go new file mode 100644 index 000000000..f80a896d3 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg2/pkg2.go @@ -0,0 +1,11 @@ +package pkg2 + +import ( + "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg3" +) + +var A int + +func init() { + pkg3.A = 2 +} diff --git a/pkg/compiler/testdata/importcycle/pkg3/pkg3.go b/pkg/compiler/testdata/importcycle/pkg3/pkg3.go new file mode 100644 index 000000000..35abab456 --- /dev/null +++ b/pkg/compiler/testdata/importcycle/pkg3/pkg3.go @@ -0,0 +1,11 @@ +package pkg3 + +import ( + "github.com/nspcc-dev/neo-go/pkg/compiler/testdata/importcycle/pkg2" +) + +var A int + +func init() { + pkg2.A = 1 +}