Stop counting stale ELF strings when bottling - #23644
Conversation
|
Thanks for your pull request. This has been closed because it appears to be missing the pull request template, perhaps because this was written by an AI not a human. We require humans to read and fill in these templates. Please edit this pull request to fill in the current pull request template. This workflow will reopen this pull request automatically once the template is complete. Do not open a new pull request for this. |
There was a problem hiding this comment.
Pull request overview
Updates bottling scans to ignore stale ELF prefix strings left by patchelf while preserving live references.
Changes:
- Adds ELF-aware match filtering.
- Adds regression tests for stale and live strings.
- Removes the completed relocation-plan item.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Summary | Findings |
|---|---|---|
Library/Homebrew/test/keg_relocate/elf_checker_spec.rb |
Adds ELF filtering regression coverage. | None |
Library/Homebrew/plans/relocatable-bottles.md |
Removes the completed plan item. | None |
Library/Homebrew/keg_relocate.rb |
Implements ELF-aware filtering. | Two moderate findings (4 votes each): account for DT_CONFIG, DT_DEPAUDIT, and DT_AUDIT; rescue parser truncation errors such as IOError/EOFError. |
Suppressed comments (3)
Library/Homebrew/keg_relocate.rb:540
- The vendored
elftoolsdefinesDT_FILTERas0x7ffffffe, the same value asDT_USED, while the ELF ABI value forDT_FILTERis0x7fffffff. Thus an actualDT_FILTERtag is not added tolive_string_offsets(and aDT_USEDvalue is treated as a string offset), so a live filter path can be discarded. Correct the dependency constant or account for the ABI value here.
ELFTools::Constants::DT::DT_FILTER,
Library/Homebrew/keg_relocate.rb:572
match_rangecovers the entire printable run returned bystrings, not the specific prefix occurrence being reported. For example, if a dynamic tag points at the interiorlibfoo.soof/old/prefix/libfoo.so, the live offset lies in this range and the unreferenced/old/prefixis retained, so this still pins a stale suffix-merged prefix. Track the byte range of the actual matched occurrence before deciding it is live.
# A string some dynamic tag still points into is live, including
# references into the middle of a suffix-merged string.
next true if live_string_offsets.any? { |live| match_range.cover?(live) }
Library/Homebrew/keg_relocate.rb:536
- The dynamic string table is also indexed by loader-visible structures such as
.dynsymsymbolst_nameentries (and version tables), not only by the string-valued dynamic tags listed here. A prefix-containing live symbol name will therefore be treated as an unreferenced.dynstrstring and dropped. Preserve offsets referenced by the dynamic symbol/version tables before classifying the remainder as dead.
# Dynamic tags whose value is an offset into the dynamic string
# table, i.e. the strings the loader can actually see.
string_tags = [
ELFTools::Constants::DT::DT_NEEDED,
ELFTools::Constants::DT::DT_SONAME,
馃挕 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
0796227 to
17c8937
Compare
17c8937 to
97ea33c
Compare
There was a problem hiding this comment.
I don't know if we can justify treating every match outside the section table as dead, which seems to be what this approach does implicitly.
ELFFile#sections reflects only the section headers, while strings - scans the whole file. ELF execution is described by program headers, not just sections, so I think we can pick up text matches in non-section data but mistakenly classify them as non-live.
Also: I think Copilot's suppressed comments contain correctness issues that shouldn't have been suppressed.
|
I think we want to keep the exception narrow here. We only need to identify strings that are demonstrably stale artefacts left behind by |
I disagree. As the person who wrote the original I'll look at all the comments here including the suppressed one but just want to be explicit that the there is an active goal here to be less "safe" and prioritise removing false negatives over false positives which we can trivially fix if we get bug reports. |
f36bcda to
0486417
Compare
- Growing an ELF RPATH or interpreter makes patchelf move the dynamic string table or interpreter elsewhere in the file, leaving the old prefix string behind as dead bytes that `strings`-based scanning in `brew bottle` still found, wrongly pinning bottles (e.g. `harfbuzz` and the glib/gobject-introspection cluster) whose live linkage is fully placeholdered. - `Keg.text_matches_in_file` now maps each match offset back to the ELF structures with the vendored elftools and drops matches the loader cannot see: unreferenced strings in loader-owned regions (`.dynstr`, `.interp` and the `DT_STRTAB` table) and bytes outside every section. - Strings still referenced by dynamic tags (including references into the middle of a suffix-merged string), the live `PT_INTERP` value and strings compiled into ordinary sections keep pinning bottles. - These formulae flip to `cellar :any` on their next rebottle. This change is part of [`plans/relocatable-bottles.md`](https://github.com/Homebrew/brew/blob/HEAD/Library/Homebrew/plans/relocatable-bottles.md)
0486417 to
3f33af7
Compare
string table or interpreter elsewhere in the file, leaving the old
prefix string behind as dead bytes that
strings-based scanning inbrew bottlestill found, wrongly pinning bottles (e.g.harfbuzzand the glib/gobject-introspection cluster) whose live linkage is
fully placeholdered.
Keg.text_matches_in_filenow maps each match offset back to theELF structures with the vendored elftools and drops matches the
loader cannot see: unreferenced strings in loader-owned regions
(
.dynstr,.interpand theDT_STRTABtable) and bytes outsideevery section.
the middle of a suffix-merged string), the live
PT_INTERPvalueand strings compiled into ordinary sections keep pinning bottles.
cellar :anyon their next rebottle.This change is part of
plans/relocatable-bottles.mdbrew benchmarkresults.brewcommands to reproduce the bug?brew lgtm(style, typechecking and tests) locally?Claude Fable 5 with local review and testing.