-
Notifications
You must be signed in to change notification settings - Fork 46
Description
Summary
When a type embeds another type from a different package to implement an interface that has unexported methods, the interface method table (itab) contains nil function pointers for those unexported methods. This causes a runtime panic when the interface method is called.
Root Cause
In ssa/abitype.go:426-434, when generating the method table for a type, unexported methods from other packages have their Ifn_ (interface function pointer) set to nil:
if !token.IsExported(mName) {
name = b.Str(abi.FullName(mPkg, mName)).impl
skipfn = PathOf(mPkg) != pkgPath // true when method is from another package
}
// ...
if skipfn {
tfn = prog.Nil(prog.VoidPtr()).impl
ifn = tfn // nil!
}This means when go/types.(*Scope).Insert calls obj.setParent(s) (an unexported interface method), it attempts to call a nil function pointer.
Minimal Reproduction
package main
import (
"go/token"
"go/types"
)
// wrappedFunc embeds *types.Func to implement types.Object
type wrappedFunc struct {
*types.Func
}
func main() {
pkg := types.NewPackage("test", "test")
scope := pkg.Scope()
// Create a types.Func
sig := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := types.NewFunc(token.NoPos, pkg, "testFunc", sig)
// Wrap it
wrapped := &wrappedFunc{Func: fn}
// Convert to types.Object interface
var obj types.Object = wrapped
// This crashes because setParent (unexported method) has nil function pointer
scope.Insert(obj)
println("OK")
}Steps to Reproduce
llgo run main.goExpected Behavior
Program prints "OK" and exits normally.
Actual Behavior
panic: runtime error: invalid memory address or nil pointer dereference
[... go/types.(*Scope).Insert+0x18 ...]
Analysis
The types.Object interface has 17 methods (8 exported + 9 unexported). When *wrappedFunc implements this interface through embedding *types.Func:
- Exported methods (Name, String, etc.): Work correctly, have valid function pointers
- Unexported methods (setParent, setType, etc.): Have
Ifn_ = 0x0because they're fromgo/typespackage
When scope.Insert(obj) internally calls obj.setParent(s), it reads the nil function pointer from the itab and crashes.
Environment
- llgo version: latest main branch
- Go version: 1.24
- OS: macOS (arm64)