Skip to content

go1.26 linux/arm64: minimal godebug-style wrapper crashes with nil pointer dereference #1757

@cpunion

Description

@cpunion

On goplus/main, a small godebug-style wrapper package crashes under llgo on linux/arm64 + go1.26.0.

This is a reduced repro for the pattern used by Go 1.26's crypto/internal/fips140deps/godebug wrapper:

  • current package name and imported package name are both godebug
  • type Setting godebug.Setting
  • pointer reinterpretation between *Setting and *godebug.Setting

Expected: the program prints OK.
Actual: llgo run . panics with invalid memory address or nil pointer dereference.

Minimal repro

internal/godebug/godebug.go

package godebug

import "sync"

type Setting struct {
	name string
	once sync.Once
}

func New(name string) *Setting {
	return &Setting{name: name}
}

func (s *Setting) Value() string {
	s.once.Do(func() {
		if s.name == "" {
			s.name = "default"
		}
	})
	return s.name
}

godebug/godebug.go

package godebug

import "github.com/goplus/llgo/_demo/go/godebug_alias_run/internal/godebug"

type Setting godebug.Setting

func New(name string) *Setting {
	return (*Setting)(godebug.New(name))
}

func (s *Setting) Value() string {
	return (*godebug.Setting)(s).Value()
}

func Value(name string) string {
	return godebug.New(name).Value()
}

main.go

package main

import (
	"fmt"

	"github.com/goplus/llgo/_demo/go/godebug_alias_run/godebug"
)

func main() {
	if got := godebug.Value("hello"); got != "hello" {
		panic(fmt.Sprintf("Value(hello)=%q, want hello", got))
	}
	if got := godebug.New("world").Value(); got != "world" {
		panic(fmt.Sprintf("New(world).Value()=%q, want world", got))
	}
	if got := godebug.New("").Value(); got != "default" {
		panic(fmt.Sprintf("New(\"\").Value()=%q, want default", got))
	}
	fmt.Println("OK")
}

Repro matrix

Pass

Ordinary Go toolchain:

cd _demo/go/godebug_alias_run
go run .
# OK

llgo on linux/arm64 + go1.24.2:

./dev/docker.sh arm64 bash -lc 'cd /repo && cd _demo/go/godebug_alias_run && /repo/dev/llgo.sh run .'
# OK

Fail

llgo on linux/arm64 + go1.26.0:

./dev/docker.sh arm64 bash -lc 'set -euo pipefail; cd /repo; export GOTOOLCHAIN=go1.26.0; cd _demo/go/godebug_alias_run; /repo/dev/llgo.sh run .'

Output:

panic: runtime error: invalid memory address or nil pointer dereference

[0xB023DAD8 (null)+0x0, SP = 0xb02bade8]
[0xB023DB14 (null)+0x0, SP = 0xb02bade8]
[0xB01B4060 (null)+0x0, SP = 0xb02bade8]
[0xB01B4038 (null)+0x0, SP = 0xb02bade8]
[0xB0192C78 (null)+0x0, SP = 0xb02bade8]
[0xB0190A38 (null)+0x0, SP = 0xb02bade8]
[0xB01901A4 (null)+0x0, SP = 0xb02bade8]
[0xB0176E20 (null)+0x0, SP = 0xb02bade8]
[0xB016A3E4 (null)+0x0, SP = 0xb02bade8]
[0xB0167484 (null)+0x0, SP = 0xb02bade8]
[0xB0167440 (null)+0x0, SP = 0xb02bade8]
[0x9AC384C4 (null)+0x0, SP = 0xb02bade8]
[0x9AC38598 __libc_start_main+0x11, SP = 0x98]
[0xB0167330 __libc_start_main+0x11, SP = 0x98]
exit status 2

Notes

I also tried linux/amd64 + go1.26.0, but that path currently fails earlier on an existing blocker:

internal/runtime/gc/scan: .../expand_amd64.s: missing Go declaration for asm symbol "expandAVX512_1"

So the reduced repro above is confirmed on linux/arm64, and not yet isolated on linux/amd64 because of that earlier failure.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions