Repository navigation
romfs: make the per-file size cap effective (closes #68) - #69
Merged
Merged
Conversation
The romfs size field (header offset 8) is 32-bit, but MAX_FILE_BYTES was 8 GiB and the guard compared the uint32_t size against it, so the comparison was always true and the cap was dead code (clang -Wtautological-constant-out-of-range-compare). The read that follows is bounds-checked, so this was not a memory-safety bug, but the guard that was meant to bound a single allocation from a crafted size field never fired. Lower MAX_FILE_BYTES to 1 GiB, which is representable within the 32-bit size field (the whole image is already bounded to <4 GiB by the 32-bit full_size field) and is a generous ceiling for a read-only romfs file. Clamp an oversized declared size to the cap and mark the result partial, matching how the ext/reiserfs/nilfs2 extractors handle an oversized size, instead of trusting the field. Adds tests/test_romfs_sizecap.py: builds a real romfs, patches one regular file's size field to 0xFFFFFFFF, and checks moria clamps it, reports partial, does not crash (ASan oracle) and does not emit a multi-gigabyte file, while the intact sibling file still extracts. Closes #68.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a dead-code size guard in the romfs extractor. Closes #68.
The romfs on-disk
sizefield (header offset 8) is 32-bit, so*sizeis auint32_tbounded at ~4 GiB.MAX_FILE_BYTESwas 8 GiB, so*size <= MAX_FILE_BYTESwas always true and the guard did nothing. clang flagged it:
This was not a memory-safety bug (the following
Reader::bytesis bounds-checkedagainst the image, so an oversized size reads nothing rather than over-reading).
The latent problem is resource use: the cap was meant to bound a single
allocation from a crafted size field, and it never fired.
Change
MAX_FILE_BYTESto 1 GiB. The value has to be representable within the32-bit size field to mean anything; 1 GiB is a generous ceiling for a read-only
romfs file, whose whole image is already bounded to <4 GiB by the 32-bit
full_sizefield.partial,matching how the ext/reiserfs/nilfs2 extractors handle an oversized size,
rather than trusting the field.
Tests
tests/test_romfs_sizecap.py(wired intorun.shand ctest): builds a realromfs with the bundled
mkromfs.py, patches one regular file's 32-bit size fieldto
0xFFFFFFFF, and checks that moria clamps it, reportspartial, does notcrash (the ASan build is the out-of-bounds / allocation oracle), and does not
emit a multi-gigabyte file, while the intact sibling file still extracts.
The existing romfs round-trip in
test_extract.pystill passes, and the warningis gone from the build.