Skip to content

fix(filesystem): zero-fill newly exposed file ranges - #100

Merged
srpatcha merged 1 commit into
embeddedos-org:masterfrom
BhavarSingh:fix/ramfs-zero-fill
Aug 31, 2026
Merged

fix(filesystem): zero-fill newly exposed file ranges#100
srpatcha merged 1 commit into
embeddedos-org:masterfrom
BhavarSingh:fix/ramfs-zero-fill

Conversation

@BhavarSingh

Copy link
Copy Markdown
Contributor

Summary

The RAM filesystem retained old bytes in its fixed inode buffer after
EOS_O_TRUNC. Growing that file with eos_fs_truncate(), or seeking past EOF
and writing, made those discarded bytes readable again instead of exposing
zero-filled storage.

This change zero-fills every newly readable range while preserving existing
capacity clamping, shrinking, and ordinary read/write behavior.

Type of Change

  • fix — Bug fix
  • test — Add or fix tests

Changes

  • Clear the gap from the old EOF to the write position before a sparse write.
  • Clear the newly exposed range when truncation grows a file.
  • Document both zero-fill guarantees in the public filesystem header.
  • Add regressions for growth and sparse writes after stale sensitive contents
    were discarded with EOS_O_TRUNC.

Testing

  • Warning-clean focused compile with -Wall -Wextra -Werror
  • Filesystem executable: 15/15 passed
  • New tests added for new functionality
  • The regression aborts on its stale-byte assertion against the old source
  • Generic/RTOS full C build passed
  • Python suites: 10 passed

Pre-Submission Checklist

  • Code compiles without warnings (-Wall -Wextra -Werror for C)
  • Relevant existing tests pass
  • New tests added for new functionality
  • Documentation updated if API changed
  • Commit messages follow <type>(<scope>): <description> convention
  • Branch is based on latest master

Related Issues

None.

Screenshots / Logs

Not applicable.

Additional Notes

  • Host CTest execution is unverified because this Windows cross-build records
    extensionless paths for PE test executables; the focused binary was run
    directly instead.
  • The separate oversized-write length wrap in eos_fs_write() is already
    addressed by fix(filesystem): avoid write length wrap when clamping #95. This PR deliberately does not duplicate that change,
    though the adjacent edits may cause a trivial merge conflict.
  • Append semantics, descriptor permissions, and the fixed RAMFS capacity are
    unchanged.

@srpatcha
srpatcha merged commit a0df2d5 into embeddedos-org:master Aug 31, 2026

@srpatcha srpatcha left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving. This is an information-disclosure fix, and the test earns its place.

The defect

eos_fs_truncate() zeroed on shrink and not on growth. So the sequence

write("secret");  truncate(0);  truncate(6);  read()

returns secret. The bytes were never cleared — only n->size moved — so
shrinking a file and growing it back republishes whatever was there. Anything
that treats truncation as deletion is wrong on this filesystem, and the naming in
your test (/secret, "must not make discarded contents readable again") is the
right framing: this is disclosure, not a correctness nit.

Verified

Applied on current master:

0 build errors
100% tests passed, 0 tests failed out of 28

Then reverted only the growth branch, restoring the shrink-only form:

test_filesystem.c:81: test_fs_truncate_growth_zero_fills_stale_bytes:
Assertion `memcmp(buf, zeros, sizeof(buf)) == 0' failed.
0% tests passed, 1 tests failed out of 1

Fails on the unfixed code, passes on the fixed one. That is what separates a
regression test from a demonstration, and it is worth saying because two tests I
have looked at this week did not manage it — one asserted on values correct
before and after the bug, and another (mine) used an input that happened not to
trigger the defect.

The seek-past-EOF gap fill is the same class caught in the same pass:

if (p > n->size) memset(n->data + n->size, 0, p - n->size);

Writing after seeking beyond EOF previously left whatever was in the buffer
visible in the gap.

On the evidence row

Thank you for stating what you could not verify:

Host CTest launch is unverified because the Windows cross-build emits
extensionless PE test paths.

That is more useful than an unqualified "all tests pass", and it let me spend my
verification where it mattered rather than re-checking what you had already
covered. For what it is worth, host CTest does run cleanly on Linux — 28/28 — so
that gap is a Windows toolchain artefact rather than anything about this change.

Also correct to point at #95 for the separate write-length overflow rather than
folding it in. That one is approved and covers p + len > n->cap wrapping when
len is near SIZE_MAX. Both touch filesystem.c; whichever lands second will
need a trivial rebase, and there is no semantic disagreement between them.

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