Skip to content

romfs: make the per-file size cap effective (closes #68) - #69

Merged
nmatt0 merged 1 commit into
masterfrom
fix/romfs-size-cap
Oct 22, 2026
Merged

nmatt0 merged 1 commit into
masterfrom
fix/romfs-size-cap

Conversation

@nmatt0

@nmatt0 nmatt0 commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes a dead-code size guard in the romfs extractor. Closes #68.

The romfs on-disk size field (header offset 8) is 32-bit, so *size is a
uint32_t bounded at ~4 GiB. MAX_FILE_BYTES was 8 GiB, so *size <= MAX_FILE_BYTES
was always true and the guard did nothing. clang flagged it:

src/extract/romfs.cpp:84: result of comparison of constant 8589934592 with
expression of type 'unsigned int' is always true
[-Wtautological-constant-out-of-range-compare]

This was not a memory-safety bug (the following Reader::bytes is bounds-checked
against 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

  • Lower MAX_FILE_BYTES to 1 GiB. The value has to be representable within the
    32-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_size field.
  • Clamp an oversized declared size to the cap and mark the result partial,
    matching how the ext/reiserfs/nilfs2 extractors handle an oversized size,
    rather than trusting the field.

Tests

tests/test_romfs_sizecap.py (wired into run.sh and ctest): builds a real
romfs with the bundled mkromfs.py, patches one regular file's 32-bit size field
to 0xFFFFFFFF, and checks that moria clamps it, reports partial, does not
crash (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.py still passes, and the warning
is gone from the build.

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.
@nmatt0
nmatt0 merged commit ad363f2 into master Oct 22, 2026
4 checks passed
@nmatt0
nmatt0 deleted the fix/romfs-size-cap branch October 22, 2026 18:44
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.

romfs: 8 GiB per-file size cap is dead code (32-bit size field)

1 participant