Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: Compiler regression in Go 1.16 - internal compiler error: child dcl collision on symbol #44378

Closed
gunnsth opened this issue Feb 18, 2021 · 9 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@gunnsth
Copy link

gunnsth commented Feb 18, 2021

What version of Go are you using (go version)?

$ go version
go version go1.16 linux/amd64

Does this issue reproduce with the latest release?

Yes. I believe this is the latest release. Whereas it did not occur in Go 1.12 - 1.15.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/tmp/unipdf-examples/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2823951920=/tmp/go-build -gno-record-gcc-switches"

What did you do?

$ git clone https://github.com/unidoc/unipdf-examples.git
$ cd unipdf-examples/pages
$ go build pdf_merge.go

What did you expect to see?

Nothing, i.e. successful compilation. As happens on prior Go version (1.15, 1.14, 1.13 tested).

What did you see instead?

# git clone https://github.com/unidoc/unipdf-examples.git
Cloning into 'unipdf-examples'...
remote: Enumerating objects: 94, done.
remote: Counting objects: 100% (94/94), done.
remote: Compressing objects: 100% (82/82), done.
remote: Total 1732 (delta 29), reused 31 (delta 9), pack-reused 1638
Receiving objects: 100% (1732/1732), 5.90 MiB | 1.82 MiB/s, done.
Resolving deltas: 100% (1115/1115), done.
root@e352d91b0d67:/tmp# cd unipdf-examples/pages
root@e352d91b0d67:/tmp/unipdf-examples/pages# go build pdf_merge.go
go: downloading github.com/unidoc/unipdf/v3 v3.18.0
go: downloading github.com/unidoc/pkcs7 v0.0.0-20200411230602-d883fd70d1df
go: downloading github.com/unidoc/unitype v0.2.1
go: downloading golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
go: downloading golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
go: downloading golang.org/x/text v0.3.5
go: downloading github.com/unidoc/timestamp v0.0.0-20200412005513-91597fd3793a
go: downloading golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
go: downloading github.com/stretchr/testify v1.6.1
go: downloading gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading github.com/sirupsen/logrus v1.7.0
go: downloading golang.org/x/sys v0.0.0-20200413165638-669c56c373c4
# github.com/unidoc/unipdf/v3/model
<autogenerated>:1: internal compiler error: child dcl collision on symbol _geffa within "".(*PdfAppender).replaceObject


Please file a bug report including a short program that triggers the error.
https://golang.org/issue/new

This was originally reported in: unidoc/unipdf#437

@toothrot toothrot changed the title Compile regression in Go 1.16 - internal compiler error: child dcl collision on symbol cmd/compile: Compiler regression in Go 1.16 - internal compiler error: child dcl collision on symbol Feb 18, 2021
@toothrot toothrot added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 18, 2021
@toothrot toothrot added this to the Backlog milestone Feb 18, 2021
@toothrot
Copy link
Contributor

/cc @randall77 @griesemer

@ianlancetaylor
Copy link
Contributor

CC @thanm

@thanm thanm self-assigned this Feb 19, 2021
@thanm
Copy link
Contributor

thanm commented Feb 19, 2021

Thanks, I'll take a look.

@thanm thanm added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Feb 19, 2021
@thanm
Copy link
Contributor

thanm commented Feb 19, 2021

This is definitely an oddball of a bug.

The code in question is from https://github.com/unidoc/unipdf. For some reason, the author(s) of this code have run it through an obfuscating tool, which renames local variables and compacts a lot of code down into a single line. Here is the offending line of code in its original form:

func (_bbfa *PdfColorCalRGB )ToInteger (bits int )[3]uint32 {_fdbd :=_ag .Pow (2,float64 (bits ))-1;return [3]uint32 {uint32 (_fdbd *_bbfa .A ()),uint32 (_fdbd *_bbfa .B ()),uint32 (_fdbd *_bbfa .C ())};};func (_affae *PdfAppender )replaceObject (_agaf ,_adgf _aa .PdfObject ){switch _cecg :=_agaf .(type ){case *_aa .PdfIndirectObject :_affae ._dcbb [_adgf ]=_cecg .ObjectNumber ;case *_aa .PdfObjectStream :_affae ._dcbb [_adgf ]=_cecg .ObjectNumber ;};};

The function that triggers the problem is "replaceObject" above; prior to 1.16 we would not inline this function (since it contains a type switch). Now that we're inlining, it exposes a problem in the DWARF-gen code.

Here is a slightly smaller reproducer:

package a

type O interface{}
type IO int
type OS int

type A struct {
	x int
}

// original versions of the two functions
func (p *A) UO(o O) {
	p.r(o, o)
}
func (p *A) r(o1, o2 O) {
	switch x := o1.(type) {
	case *IO:
		p.x = int(*x)
	case *OS:
		p.x = int(*x + 2)
	}
}

// now the obfuscated versions
var myverylongname0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 int ; func (p *A) UO2(o O) { p.r2(o, o); }; func (p *A) r2(o1, o2 O) { switch x := o1.(type) { case *IO:	p.x = int(*x); 	case *OS: 	p.x = int(*x + 2); } }

The problem lies with type switch in the A.r method. For this switch the compiler manufactures a new PAUTO named "x" for each arm of the switch. Ordinarily these variables would be given a unique source position (that of the line of the associated "case" clause), but here due to the obfuscation each of the temps is given the same line number. In the source code above, the variables do have different columns, but in the current implementation of the Go parser/lexer the maximum allowable column number is 255.

As a result, the DWARF code winds up seeing two AUTO variables with the same name, file, line, and column (which it is not expecting).

Given the late stage of 1.16, probably the best way to handle this is by detecting this sort of breakdown in the DWARF code, as opposed to trying to do anything with the parser's handling of columns.

I'll work on putting together a CL.

@gopherbot
Copy link

Change https://golang.org/cl/294289 mentions this issue: cmd/compile: fix panic in DWARF-gen handling obfuscated code

@thanm
Copy link
Contributor

thanm commented Feb 19, 2021

@gopherbot please consider this for backport to 1.16

@gopherbot
Copy link

Backport issue(s) opened: #44433 (for 1.16).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.

@gopherbot
Copy link

Change https://golang.org/cl/294789 mentions this issue: cmd/compile: fix panic in DWARF-gen handling obfuscated code

@gopherbot
Copy link

Change https://golang.org/cl/295129 mentions this issue: test: add test for issue 38698

gopherbot pushed a commit that referenced this issue Feb 22, 2021
It was fixed by CL 294289, for #44378.
This is a different style of test that uses
line directives instead of extremely long lines.

Fixes #38698.

Change-Id: I50a1585030978b35fffa9981d6ed96b99216dc3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/295129
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
@golang golang locked and limited conversation to collaborators Feb 22, 2022
@rsc rsc unassigned thanm Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

5 participants