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

support Go 1.21's dependable package initialization order #693

Closed
mvdan opened this issue Mar 5, 2023 · 1 comment
Closed

support Go 1.21's dependable package initialization order #693

mvdan opened this issue Mar 5, 2023 · 1 comment

Comments

@mvdan
Copy link
Member

mvdan commented Mar 5, 2023

Currently, with Go versions like 1.19 or 1.20, it's only guaranteed that:

  • Each package's dependencies are initialized before it is itself initialized
  • A package's init funcs are run in the order they appear in the source

See https://go.dev/ref/spec#Package_initialization.

It seems like Go 1.21 is adding a third rule, per golang/go#31636 (comment). With this addition, if there are multiple packages which can be initialized at the same time, the lexically earliest package is initialized first.

That would currently not work with garble, as we replace import paths with hashes, which could easily change the lexical order between packages. If the input source has packages foo/bar and foo/zzz with the same Go package imports, we must ensure that foo/bar continues to be initialized first after obfuscation.

@mvdan
Copy link
Member Author

mvdan commented Feb 18, 2024

I thought about this some more. I don't think we can keep the lexical sorting aspect of package initialization order intact, because a Go binary may include an unlimited and unknown number of Go packages in its import graph, and we load and obfuscate one package at a time by design.

So I think we should simply document that, as a caveat, the lexical sorting of import paths may change due to obfuscation, and that may change a program's package initialization order. And that, if a program needs the order to be stable, they should use package imports to enforce it.

mvdan added a commit to mvdan/garble-fork that referenced this issue Feb 18, 2024
Keeping the original lexical sorting of Go packages would be very hard,
as a Go program may import an unknown number of Go packages,
and we load and obfuscate one package at a time by design.

One option would be to load all packages upfront when obfuscating
main packages, but that would break the per-package caching of
ofbuscated Go packages, causing a huge slow-down in builds.

Another option would be to not obfuscate import paths,
which would clearly cause a worsening of the obfuscation quality.

The third option is to not attempt to keep the original order,
and document that as a caveat in the README.
I suspect the vast majority of Go projects won't be affected by this,
and those few that might be can always use imports to enforce the order.

Closes burrowers#693, per the decision above to not change what we do.
@pagran pagran closed this as completed in f08edd0 Feb 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant