-
Notifications
You must be signed in to change notification settings - Fork 18k
cmd/pack: produces malformed .a files #21703
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
Comments
I was discussing with @ianlancetaylor a week or two ago to make -pack the default behavior and remove it as a flag. Having two framing formats for package export data makes things a little unnecessarily complex. This bug further suggests to me that would be worthwhile. I don't think @griesemer or I were aware of that logic in cmd/pack. The object file format delimits the package export data with "$$", so the export data format has an escape sequence to prevent that from occurring. However, no such escape sequences exists to protect against "\n!\n". :/ I can't think of anything specific to 1.8 that would have prevented this issue, but this bug is really easy to reproduce:
|
@mdempsky Agreed (and yes, I was not aware of that logic). It should be trivial to have an additional escape mechanism (short term fix), but in the long run we should try to avoid the need for escaping in the first place (by identifying the sections in .a and .o files via their positions rather than parsing their content). |
I think the easiest fix is in cmd/pack to keep count of the number of "$$" lines, and to only recognize "\n!\n" as ending the export data when we've seen an even count. That would prevent recognizing "\n!\n" within the binary export data, and avoid needing any additional escaping mechanisms. |
Change https://golang.org/cl/60773 mentions this issue: |
I just noticed the same search-for- |
|
Change https://golang.org/cl/79135 mentions this issue: |
What version of Go are you using (
go version
)?1.7.6.
Does this issue reproduce with the latest release?
No, but the underlying issue still appears to be present.
I tried to reproduce with Go 1.9 (following the instructions below), but the package export data is different. src/cmd/pack/pack.go has not changed, so unless the export data format has changed in a way that makes this issue impossible, I think the bug still exists.
What operating system and processor architecture are you using (
go env
)?linux amd64
What did you do?
This issue was originally reported in bazel-contrib/rules_go#769. The compiler panics when building Kubernetes using Bazel and Go 1.7.6. This happens because the .a file produced for a specific target, //vendor:github.com/aws/aws-sdk-go/service/ecr, is malformed. The compiler panics when it reads the malformed .a file when building a dependent package.
I spent this morning looking into how "go build" and Bazel produce .a files. When "go build" invokes the compiler, it passes the -pack option, which produces an .a file directly. The .a file contains two files: __.PKGDEF (export data), and _go_.o (compiled code).
When Bazel invokes the compiler, it does not pass the -pack option, so the compiler produces an .o file that contains the export data and the compiled code together. These sections are separated by a
!
on a line by itself. Seedumpobj1
in cmd/compile/internal/gc/obj.go. As a separate action, Bazel creates the .a file with cmd/pack. When cmd/pack creates an archive, it looks for a!
line in the first .o file, then extracts the data above that into a __.PKGDEF file. SeereadPkgdef
in pack.go.The problem seems to be that the export data for this library contains a
!
on a line by itself without any escaping or delimitation. I don't know enough about the export data format to know what that means or how it's changed since 1.7.6. cmd/pack interprets this as the end of the export data, so it only extracts about 5K instead of 43K. Consequently, the export data is truncated, and the compiler panics when reading it back in.Steps to reproduce
This issue can be reproduced by manually running compile and pack commands and observing the output.
go build -x -work github.com/aws/aws-go-sdk/service/ecr
ar x ecr.a
. Observe that the __.PKGDEF file is about 43K.\n!\n
sequence in the file.go tool pack c ecr.a ecr.o
.ar x ecr.a
. Observe that the __.PKGDEF file is only about 5K.What did you expect to see?
The .o file that gc produces does not store the export data in a format that allows it to be safely extracted. There should either be some escaping or a length of the embedded data. Given that gc can already produce .a files that have lengths like this, it's probably better to prevent gc from emitting export data at all unless it's writing an archive.
Bazel will switch to doing what "go build" does: we'll create an .a file with -pack, then we'll append any additional .o files to it if we have them.
The text was updated successfully, but these errors were encountered: