Size the sanitised fixtures to the length under test #56

Merged
Claude merged 3 commits from test/uf-14-heap-sized-manifest-fixtures into feat/firmware-updates 2026-09-19 20:06:44 +00:00
Collaborator

Tests that hand a .rodata literal or an oversized staging buffer to a function
taking a pointer and a length put ASan's redzone past the end of the object, not
at the bound the callee was given. An over-read inside the declared length reads
valid memory and the suite stays green. The manifest tests, the session
credential tests and the digest tests all had that shape.

Each now copies into a heap buffer sized exactly to the length under test, via
one helper per file.

Proven by reintroducing a bound bug in each of the three parsers and checking the
suite before and after the fixture change:

  • manifest, a one-past-end_ read in readString: passed before, ASan
    heap-buffer-overflow after
  • terminatorAfter with its at < length guard dropped: passed before, ASan
    heap-buffer-overflow after
  • Sha256::update copying one byte more than take: passed before, ASan
    heap-buffer-overflow after

Worth knowing: the actual CCS-UF-5 over-read (480c10b, the manifest key
comparison walking w past a name's NUL) already fails the suite today as an
ASan global-buffer-overflow, because the names it over-reads are instrumented
globals. The gap this closes is the JSON body's own bound, not that one.

Tests only — no production code, specification or vectors touched, and the
test_mcp2515_tx leak suppression is unchanged. Full pio test -e native,
both node environments and host_sim all build and pass.

CCS-UF-14.

Tests that hand a `.rodata` literal or an oversized staging buffer to a function taking a pointer and a length put ASan's redzone past the end of the object, not at the bound the callee was given. An over-read inside the declared length reads valid memory and the suite stays green. The manifest tests, the session credential tests and the digest tests all had that shape. Each now copies into a heap buffer sized exactly to the length under test, via one helper per file. Proven by reintroducing a bound bug in each of the three parsers and checking the suite before and after the fixture change: - manifest, a one-past-`end_` read in `readString`: passed before, ASan heap-buffer-overflow after - `terminatorAfter` with its `at < length` guard dropped: passed before, ASan heap-buffer-overflow after - `Sha256::update` copying one byte more than `take`: passed before, ASan heap-buffer-overflow after Worth knowing: the actual CCS-UF-5 over-read (`480c10b`, the manifest key comparison walking `w` past a name's NUL) already fails the suite today as an ASan global-buffer-overflow, because the names it over-reads are instrumented globals. The gap this closes is the JSON body's own bound, not that one. Tests only — no production code, specification or vectors touched, and the `test_mcp2515_tx` leak suppression is unchanged. Full `pio test -e native`, both node environments and `host_sim` all build and pass. CCS-UF-14.
Size the credential and digest fixtures to the length under test
All checks were successful
Build and test / build (pull_request) Successful in 3m59s
Build and test / release (pull_request) Has been skipped
a5771bcd19
Claude left a comment

One minor point, on the zero-length case. Nothing blocking.

One minor point, on the zero-length case. Nothing blocking.
@ -11,0 +11,4 @@
// Heap-allocated and sized exactly to the length under test, so the sanitiser's
// redzone sits where update's bound is. A larger fixture, or a pointer into the
// middle of one, would let a read past that bound go unreported.
void feed(ctrl::Sha256& hash, const uint8_t* from, uint32_t length) {
Author
Collaborator

At length 0 the redzone is not at the bound: ASan gives new uint8_t[0] a one-byte addressable chunk (offset 0 unpoisoned, offset 1 onwards poisoned), so a one-past read at index 0 is still unreported. That hits digestOf("") in test_the_empty_input, and parseExactly("", ...) in the manifest tests (harmless there — parseFirmwareManifest returns on length == 0 before reading). The comment states the guarantee unconditionally; worth qualifying it, since there is no fixture fix.

At length 0 the redzone is not at the bound: ASan gives `new uint8_t[0]` a one-byte addressable chunk (offset 0 unpoisoned, offset 1 onwards poisoned), so a one-past read at index 0 is still unreported. That hits `digestOf("")` in `test_the_empty_input`, and `parseExactly("", ...)` in the manifest tests (harmless there — `parseFirmwareManifest` returns on `length == 0` before reading). The comment states the guarantee unconditionally; worth qualifying it, since there is no fixture fix.
Stop the fixture comments claiming a redzone at zero length
All checks were successful
Build and test / build (pull_request) Successful in 1m10s
Build and test / release (pull_request) Has been skipped
ffa15bf587
Claude left a comment

ffa15bf is comments only and the new wording holds at every length, zero included. Nothing further to act on.

ffa15bf is comments only and the new wording holds at every length, zero included. Nothing further to act on.
Claude merged commit ace73919c9 into feat/firmware-updates 2026-09-19 20:06:44 +00:00
Claude deleted branch test/uf-14-heap-sized-manifest-fixtures 2026-09-19 20:06:44 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
rob/CampervanControlSystems!56
No description provided.