5 Commits

Author SHA1 Message Date
Alex Goodman
58a033f924
Prevent unnecessary allocations when parsing compressed ELF sections (#5187)
* fix(elf): bound compressed ELF section reads

`debug/elf` takes a section's decompressed size from that section's own
compression header, and a highly compressible stream really does deliver the
bytes that header promises, so `internal/saferio` does not help: it faithfully
allocates every one of them. A 2MB input file drives `elf.NewFile` to allocate
over 10GB and return no error, which is a fatal OOM rather than a recoverable
panic.

Which sections get read is not up to the caller. `elf.NewFile` always reads the
section-name string table, and `File.Symbols` reads `.symtab` plus whatever
section its `Link` field points at, so being selective about sections is not
enough to avoid it.

New `elfutil.NewFile` is a drop-in for `elf.NewFile` that rejects a declared
decompressed size over 128MB. Every production call site goes through it, and a
ruleguard rule keeps the next one from going direct.

The check runs in two parts, since `debug/elf` expands sections at two different
times. The section-name string table is the only one `elf.NewFile` expands
itself, so it is checked against the raw bytes before the call; everything else
is expanded lazily by `(*Section).Open` and is checked after the parse, where
names, types and decompressed sizes are already resolved.

Only the sections syft can actually reach are bounded, which keeps the guard
from costing real binaries. DWARF is excluded since nothing calls `File.DWARF`,
so a large compressed `.debug_info` no longer skips the whole file, and sections
`debug/elf` will not decompress anyway (`SHF_ALLOC`, `SHT_NOBITS`) are left
alone. The legacy `.zdebug` form is matched on the section name the way
`debug/elf` gates it rather than on the `ZLIB` magic, so an ordinary section
starting with those four bytes is not mistaken for a compressed one.

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* fix(elf): gate debug/buildinfo behind the compressed-section check

`debug/buildinfo.Read` opens ELF files with `debug/elf` itself, and `elf.NewFile`
expands the section-name string table as it parses, so the golang cataloger was
still reachable by the same bomb `elfutil` exists to stop. A 261KB fixture drove
1.4GB of allocation through `buildinfo.Read` and returned no error.

`elfutil.CheckSectionNameTable` is now exported for that case: callers that cannot
use `NewFile` because the `debug/elf` call is made for them inside another package.
Both `buildinfo.Read` call sites go through it, including the UPX-decompressed one.

Also corrects claims that did not hold up:

- the package doc's 2MB-to-10GB figure is not reachable with zlib (~1000:1), so it
  now carries the measured 510KB-to-2.6GB, and names zstd's 32767:1 since that is
  what makes the small inputs possible

- `.go.buildinfo` was listed as a hot-path section elfutil covers, but it is read
  through `debug/buildinfo` and never touches `Section.Data`

- the graalvm comment claimed routing size rejections away from `*elf.FormatError`
  improved reporting; both branches are skipped by the caller and only the
  FormatError branch logs, so it did the opposite

- `sharedLibraries` logged short and truncated files as real ELF failures, since
  `debug/elf` returns a bare `io.EOF` rather than an `*elf.FormatError` for those

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* added test comments around the negative cases

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* additional tests

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* better decomposition and comments

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* use a less brittle constant for error detection

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2026-08-14 20:08:58 +00:00
Will Murphy
e38851143e
chore: centralize temp files and prefer streaming IO (#4668)
* chore: centralize temp files and prefer streaming IO

Catalogers that create temp files ad-hoc can easily forget cleanup,
leaking files on disk. Similarly, io.ReadAll is convenient but risks
OOM on large or malicious inputs.

Introduce internal/tmpdir to manage all cataloger temp storage under
a single root directory with automatic cleanup. Prefer streaming
parsers (bufio.Scanner, json/yaml.NewDecoder, io.LimitReader) over
buffering entire inputs into memory. Add ruleguard rules to enforce
both practices going forward.

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: go back to old release parsing

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* simplify to limit reader in version check

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* chore: regex change postponed

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

* simplify supplement release to limitreader

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>

---------

Signed-off-by: Will Murphy <willmurphyscode@users.noreply.github.com>
2026-03-18 10:53:51 -04:00
Alex Goodman
048df17e3d
Use values in relationship To/From fields (#2871)
* use pkg values in relationship fields

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* add linter rule for using values in relationships

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* use new cmptest package for comparing relationships

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* create cmptest for common cmp.Diff options in test

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* condense matches for relationship ruleguard

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* remove relationship type from rules

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* restore build tag

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* suggest using values

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* nil check pkgs

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-05-14 13:48:33 -04:00
Alex Goodman
ada8f009d2
Add relationships for ALPM packages (arch linux) (#2851)
* add alpm relationships

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* tweak reader linter rule to check for reader impl

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

* update JSON schema with alpm dependency information

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>

---------

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
2024-05-07 13:29:46 -04:00
William Murphy
3713d97b7b
chore: use ruleguard to test for missing defer statements (#2837)
* chore: ruleguard to enforce defer use

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* fix go.mod location

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close in linux release identifier

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: better lint suggestion

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: refactor binary classifier to defer close

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in gentoo cataloger

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: make go license parsing defer close readers

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer closing readers in alpine apm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in graalvm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in debian package parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in alpm parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in executable file cataloger

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in javascript license parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

* chore: defer close readers in go mod parser

Signed-off-by: Will Murphy <will.murphy@anchore.com>

---------

Signed-off-by: Will Murphy <will.murphy@anchore.com>
2024-05-07 05:42:29 -04:00