Skip to content

go/types: Config.FakeImportC leaves gaps in type information but reports no error #76765

@adonovan

Description

@adonovan

This program (thanks to @znkr) reproduces a crash (see below) in the satisfy pass used by the printf analyzer. (Googlers: see b/466322822 for the internal bug report.) The failing syntax is the C.intFunc selector.

package printf_test

import (
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"testing"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/passes/inspect"
	"golang.org/x/tools/go/analysis/passes/printf"
	"golang.org/x/tools/go/ast/inspector"
)

func TestFakeCgoCrash(t *testing.T) {
	const src = `package a

// typedef int (*intFunc) ();
//
// int
// bridge_int_func(intFunc f)
// {
//		return f();
// }
//
// int fortytwo()
// {
//	    return 42;
// }
import "C"
import "fmt"

type Formatter struct {
	Prefix string
}

func Foo(fo Formatter) {
	f := C.intFunc(C.fortytwo)
	fmt.Printf("%d %s\n", fo.Prefix, int(C.bridge_int_func(f)))
}
`

	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "a.go", src, parser.Mode(0))
	if err != nil {
		t.Fatal(err)
	}

	info := types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Implicits:  make(map[ast.Node]types.Object),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
		Scopes:     make(map[ast.Node]*types.Scope),
	}

	conf := types.Config{
		Importer:    importer.Default(),
		FakeImportC: true,
	}

	pkg, err := conf.Check("a", fset, []*ast.File{f}, &info)
	if err != nil {
		t.Fatal(err)
	}

	inspectRes := inspector.New([]*ast.File{f})

	pass := &analysis.Pass{
		Analyzer:  printf.Analyzer,
		Fset:      fset,
		Files:     []*ast.File{f},
		Pkg:       pkg,
		TypesInfo: &info,
		ResultOf: map[*analysis.Analyzer]interface{}{
			inspect.Analyzer: inspectRes,
		},
		Report: func(d analysis.Diagnostic) {
			// ignore reports
		},
	}

	_, err = printf.Analyzer.Run(pass)
	if err != nil {
		t.Fatalf("Analyzer.Run failed: %v", err)
	}
}
goroutine 5 [running]:
testing.tRunner.func1.2({0x102a3e660, 0x102ada330})
	/Users/adonovan/w/goroot/src/testing/testing.go:1967 +0x1a0
testing.tRunner.func1()
	/Users/adonovan/w/goroot/src/testing/testing.go:1970 +0x318
panic({0x102a3e660?, 0x102ada330?})
	/Users/adonovan/w/goroot/src/runtime/panic.go:860 +0x12c
golang.org/x/tools/refactor/satisfy.(*Finder).expr(0x68359b1ec030, {0x102aaf628, 0x68359af130f8})
	/Users/adonovan/x/tools/refactor/satisfy/find.go:401 +0x3fc
golang.org/x/tools/refactor/satisfy.(*Finder).expr(0x68359b1ec030, {0x102aaf748, 0x68359b084080})
	/Users/adonovan/x/tools/refactor/satisfy/find.go:464 +0x96c
golang.org/x/tools/refactor/satisfy.(*Finder).stmt(0x68359b1ec030, {0x102aafce8?, 0x68359b0840c0})
	/Users/adonovan/x/tools/refactor/satisfy/find.go:540 +0xc30
golang.org/x/tools/refactor/satisfy.(*Finder).stmt(0x68359b1ec030, {0x102aafe08?, 0x68359b03af90})
	/Users/adonovan/x/tools/refactor/satisfy/find.go:590 +0x7e4
golang.org/x/tools/refactor/satisfy.(*Finder).Find(0x68359b1ec030, 0x68359af16a80?, {0x68359af82bc8, 0x1, 0x68359afadec0?})
	/Users/adonovan/x/tools/refactor/satisfy/find.go:106 +0x190
golang.org/x/tools/go/analysis/passes/printf.methodImplementations(0x68359b1ea000)
	case *ast.SelectorExpr:
		if _, ok := f.info.Selections[e]; ok {
			f.expr(e.X) // selection
		} else {
			return f.info.Uses[e.Sel].Type() // qualified identifier               <--------- SEGV calling nil.Type 
		}

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugReportIssues describing a possible bug in the Go implementation.NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions