Visitar URL original
fix(elixir): use Hex package names from mix.lock by sueun-dev · Pull Request #5216 · anchore/syft · GitHub
Skip to content

fix(elixir): use Hex package names from mix.lock - #5216

Open
sueun-dev wants to merge 3 commits into
anchore:mainfrom
sueun-dev:fix-elixir-mix-lock-hex-alias
Open

sueun-dev wants to merge 3 commits into
anchore:mainfrom
sueun-dev:fix-elixir-mix-lock-hex-alias

Conversation

@sueun-dev

Copy link
Copy Markdown
Contributor

Description

mix.lock entries can use a local application alias with a different Hex package name, for example "my_json": {:hex, :jason, ...}. The parser used the lock key as the package identity, so Syft emitted pkg:hex/my_json@1.3.0 and dependency relationships pointed at my_json instead of the package published in Hex.

This uses the Hex package atom from the :hex tuple for package identity, and uses the hex: :... option when extracting dependency relationships. Git/path entries keep the existing source-specific handling.

Before this patch the new regression cases fail with pkg:hex/my_json@1.3.0; after the fix the package and relationship use pkg:hex/jason@1.3.0.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have added unit tests that cover changed behavior
  • I have tested my code in common scenarios and confirmed there are no regressions
  • I have added comments to my code, particularly in hard-to-understand sections

Issue references

None.

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>

@CAOShurong CAOShurong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at head e439bcf1 (go1.26.7 windows-amd64). Local gates: go build ./syft/pkg/cataloger/elixir/... and go vet clean; all four new cases (Test_extractMixLockDependencies/aliased_hex_dependency, TestParseMixLockHexAliasUsesPackageName, TestCataloger_RelationshipsWithHexAlias) plus the existing TestCataloger_Relationships PASS; go test ./internal/relationship/... ok.

The fix itself is correct and well-covered: for "my_json": {:hex, :jason, "1.3.0", ...} the parser now emits pkg:hex/jason@1.3.0 with Name: jason, and extractMixLockDependencies rewrites the consumer's dep atom {:my_json, ...} to jason via the hex: :jason option, so purls and relationship endpoints stay consistent on both sides. Testing the alias in both unit and cataloger/relationship layers is the right call.

One substantive finding: your own new test fails on Windows checkouts � and it exposes a real parser robustness gap. With core.autocrlf=true, TestParseMixLockHexAliasUsesPackageName fails: PkgHashExt comes back as " " instead of "bbb" (the other two elixir failures reproduce identically on base bf82010f; this third one is introduced here). Root cause: parseMixLock reads lines with ReadString(' ') and splits on [%{} " ,:]+ � no in the class � so tokens[len(tokens)-2] lands one slot short on CRLF input.

This is more than a dev-environment nit: when Syft scans a container layer or tar, .gitattributes normalization does not apply, and a mix.lock saved with CRLF endings already produces corrupted PkgHashExt on main today. Suggested one-liner (verified locally: with this change the whole ./syft/pkg/cataloger/elixir/... suite goes green on a Windows checkout except the pre-existing globs path-separator artifact):

var mixLockDelimiter = regexp.MustCompile(`[%{}
" ,:]+`)

Minor, non-blocking:

  1. The alias rewrite in extractMixLockDependencies also fires on git/path dep lists; those packages are never emitted, so a rewritten name there just dangles. Harmless today, but worth a one-line comment so a future reader knows the rewrite is only meaningful for hex-backed entries.
  2. �hex:\s*:(\w+) could in principle match inside a quoted string value; base16 checksums cannot contain :, so practically safe.

Happy to re-run gates on any revision.

@CAOShurong CAOShurong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at head e439bcf1 (go1.26.7 windows-amd64). Local gates: go build ./syft/pkg/cataloger/elixir/... and go vet clean; all four new cases (Test_extractMixLockDependencies/aliased_hex_dependency, TestParseMixLockHexAliasUsesPackageName, TestCataloger_RelationshipsWithHexAlias) plus the existing TestCataloger_Relationships PASS; go test ./internal/relationship/... ok.

The fix itself is correct and well-covered: for "my_json": {:hex, :jason, "1.3.0", ...} the parser now emits pkg:hex/jason@1.3.0 with Name: jason, and extractMixLockDependencies rewrites the consumer's dep atom {:my_json, ...} to jason via the hex: :jason option, so purls and relationship endpoints stay consistent on both sides. Testing the alias in both unit and cataloger/relationship layers is the right call.

One substantive finding: your own new test fails on Windows checkouts — and it exposes a real parser robustness gap. With core.autocrlf=true, TestParseMixLockHexAliasUsesPackageName fails: PkgHashExt comes back as " " instead of "bbb" (the other two elixir failures reproduce identically on base bf82010f; this third one is introduced here). Root cause: parseMixLock reads lines with ReadString(' ') and splits on [%{} " ,:]+ — no in the class — so tokens[len(tokens)-2] lands one slot short on CRLF input.

This is more than a dev-environment nit: when Syft scans a container layer or tar, .gitattributes normalization does not apply, and a mix.lock saved with CRLF endings already produces corrupted PkgHashExt on main today. Suggested one-liner (verified locally: with this change the whole ./syft/pkg/cataloger/elixir/... suite goes green on a Windows checkout except the pre-existing globs path-separator artifact):

var mixLockDelimiter = regexp.MustCompile(`[%{}
" ,:]+`)

Minor, non-blocking:

  1. The alias rewrite in extractMixLockDependencies also fires on git/path dep lists; those packages are never emitted, so a rewritten name there just dangles. Harmless today, but worth a one-line comment so a future reader knows the rewrite is only meaningful for hex-backed entries.
  2. �hex:\s*:(\w+) could in principle match inside a quoted string value; base16 checksums cannot contain :, so practically safe.

Happy to re-run gates on any revision.

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
@sueun-dev

Copy link
Copy Markdown
Contributor Author

Thanks, reproduced the CRLF failure locally. I pushed a follow-up commit (ba9b82ba) that adds \r to the mix.lock delimiter and adds a CRLF regression around the alias fixture. I also added the small comment around the dependency rewrite.

Checks rerun:

  • go test ./syft/pkg/cataloger/elixir -run 'TestParseMixLockHexAliasUsesPackageName|Test_extractMixLockDependencies|TestCataloger_RelationshipsWithHexAlias' -count=20
  • go test ./syft/pkg/cataloger/elixir -count=20
  • go test ./syft/pkg/cataloger/elixir/... -count=1
  • go test ./syft/pkg/cataloger/elixir ./internal/relationship/... -count=1
  • go test -race ./syft/pkg/cataloger/elixir -run 'TestParseMixLockHexAliasUsesPackageName|Test_extractMixLockDependencies|TestCataloger_RelationshipsWithHexAlias' -count=5
  • go build ./syft/pkg/cataloger/elixir/...
  • go vet ./syft/pkg/cataloger/elixir
  • go test ./cmd/syft -run '^$' -count=1
  • git diff --check

For ./cmd/syft, I first had to run go mod download; the same command then passed with GOPROXY=off.

@CAOShurong CAOShurong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed exact head ba9b82ba. The production fix is correct: adding \r to mixLockDelimiter fixes the CRLF hash parsing, and the focused alias/dependency behavior is otherwise green. The new CRLF regression test has a Windows-specific resource-lifetime failure, though:

go test ./syft/pkg/cataloger/elixir \
  -run 'TestParseMixLockHexAliasUsesPackageName|Test_extractMixLockDependencies|TestCataloger_RelationshipsWithHexAlias' \
  -count=20

On Windows this fails on every run during t.TempDir() cleanup:

TempDir RemoveAll cleanup: ...\mix.lock: The process cannot access the file because it is being used by another process.

pkgtest.TestFileParser opens the fixture in CatalogTester.FromFile, and TestParser does not close that reader. Existing repository fixtures hide this because they are not deleted at test cleanup; the new temporary file makes the leaked handle observable.

A focused local fix is to avoid the temporary file and feed the CRLF content through the existing in-memory helper:

pkgtest.NewCatalogTester().
    FromString(srcFixture, strings.ReplaceAll(string(content), "\n", "\r\n")).
    Expects(expectedMixLockAliasPackages(srcFixture), nil).
    TestParser(t, parseMixLock)

With that adjustment, the same focused command passes 20/20. The rest of the Elixir package passes when excluding the already-known Windows path-separator-only TestCataloger_Globs; go build ./syft/pkg/cataloger/elixir/..., go vet ./syft/pkg/cataloger/elixir, and git diff --check pass. Race execution is NOT_RUN locally because this Go setup has CGO disabled.

Please switch the CRLF regression to the in-memory reader (or otherwise ensure the opened fixture is closed) so it is portable on Windows.

Disclosure: I used AI assistance for source tracing and local verification; all commands and the minimal test adjustment above were run and checked locally.

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
@sueun-dev

Copy link
Copy Markdown
Contributor Author

Thanks, I checked the helper path and pushed a follow-up commit (7150eeea) that switches the CRLF regression from a temporary fixture on disk to pkgtest.NewCatalogTester().FromString(...). That keeps the same fixture location in expectations while avoiding the open temp-file handle on Windows.

Reran after the change:

  • go test ./syft/pkg/cataloger/elixir -run 'TestParseMixLockHexAliasUsesPackageName|Test_extractMixLockDependencies|TestCataloger_RelationshipsWithHexAlias' -count=20
  • go test ./syft/pkg/cataloger/elixir -count=20
  • go test ./syft/pkg/cataloger/elixir/... -count=1
  • go test ./syft/pkg/cataloger/elixir ./internal/relationship/... -count=1
  • go test -race ./syft/pkg/cataloger/elixir -run 'TestParseMixLockHexAliasUsesPackageName|Test_extractMixLockDependencies|TestCataloger_RelationshipsWithHexAlias' -count=5
  • go build ./syft/pkg/cataloger/elixir/...
  • go vet ./syft/pkg/cataloger/elixir
  • go test ./cmd/syft -run '^$' -count=1
  • GOOS=windows GOARCH=amd64 go test -c ./syft/pkg/cataloger/elixir
  • git diff --check

All passed locally. The Windows command is compile-only; I can't execute a Windows test binary from this macOS runner.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants