Fix M1/M2/M3: ADR-006 record gap + aligned record coverage + dead Struct arm (review #006)

M1: field_variable_kind (offset_map) now matches Record — a non-final
inline length-prefixed record field in aligned mode hits the ADR-006
rejection instead of computing silently corrupt offsets (probe-verified
clobber in the review: counts prefix at 0, id at 4).

M2: aligned record path locked with public-path tests —
materialize_aligned roundtrip (record<uint16>, wire arithmetic
asserted) and engine validate_bytes roundtrip + corrupted-buffer
rejection (record<uint32>). Record-as-last-field is the only safe
inline position post-M1.

M3: read_field's unreachable Struct arm (no struct-path entry ever
exists in an OffsetMap) replaced with a documented defensive Offset
error; doc comment states struct paths have no entry and the Offset
miss is the reachable composite failure. FieldValue::Struct (public
API, constructed by the packed reader) untouched.

Tests: 7 new (2 offset_map, 2 materialize, 1 engine M3 lock, plus the
roundtrip pair). 508 tests green, clippy -D warnings clean, wasm32
build green, cargo doc zero warnings.
This commit is contained in:
glm-5.3-flash committed 2026-09-02 19:40:09 +00:00
1 parent 5e74b991ac
commit dcfe9d16ff
4 files changed
+247 -17

No files matched your search

+57 -9
View File
@@ -1,5 +1,5 @@
---
status: in-progress (H1, L1, H3, L5, L6, H2 resolved 2026-09-02)
status: in-progress (H1, L1, H3, L5, L6, H2, M1, M2, M3 resolved 2026-09-02)
last_updated: 2026-09-02
reviewed_artifacts:
- src/read_plan.rs
@@ -95,14 +95,13 @@ sub-types, `fingerprint()` methods; `Hash` on `Endian`/
| Severity | Count | Status |
|----------|------:|--------|
| High | 3 (H1, H2, H3) | H1, H2, H3 resolved 2026-09-02 |
| Medium | 4 (M1, M2, M3, M4) | open |
| High | 3 (H1, H2, H3) | all resolved 2026-09-02 |
| Medium | 4 (M1, M2, M3, M4) | M1, M2, M3 resolved 2026-09-02; M4 ongoing |
| Low | 6 (L1–L6) | L1, L5, L6 resolved 2026-09-02 |
| Nit | 2 (N1, N2) | open |
All three Highs are now resolved. The remaining work is Medium/Low/Nit:
M1+M2 (same file, one session), M3 (trivial), M4 (per-fix posture), and
L2/L3/L4/N1/N2 opportunistic.
All three Highs and three of four Mediums are resolved. Remaining:
M4 (ongoing per-fix coverage posture), L2/L3/L4/N1/N2 opportunistic.
The three Highs are adversarial-input crashes (H1, H2) and a
cross-consumer wire-layout convention gap (H3) — all three are the
@@ -134,6 +133,10 @@ them became materially easier to hit with the 0.3.0 surface.
all three standalone walkers; full cyclic/deep-nesting/diamond test
family added. 501 tests green, clippy `-D warnings` clean, wasm build
green, `cargo doc --no-deps` zero warnings.
- **M1 + M2 + M3 (2026-09-02):** resolved in one commit (same file /
adjacent surfaces, per the recommended order) — see the resolution
blocks on each finding. 508 tests green, clippy `-D warnings` clean,
wasm build green, `cargo doc --no-deps` zero warnings.
---
@@ -586,6 +589,16 @@ position") already covers records correctly. Add the
`non_final_record_rejected_in_aligned_mode` test mirroring
`non_final_inline_string_rejected_in_aligned_mode`.
**Resolution (2026-09-02):** exactly the recommended fix —
`field_variable_kind` now matches `BastType::Record(_) =>
Some(AlkTypeKind::Record)` (with a doc comment noting the
prefix-then-variable shape and the M1 hole it closes). Tests added
mirroring the string family: `non_final_record_rejected_in_aligned_mode`
(Offset error, path `counts`, message contains ADR-006 + "record") and
`final_inline_record_allowed_in_aligned_mode` (record-as-last-field
computes `counts` prefix @ 4, total 8 — the M2 position). Done with M2
in the same commit.
### M2. Aligned-mode record fields are untested end-to-end and sit right next to the M1 hole
**Files**: `src/materialize.rs:880-893` (aligned record dispatch),
@@ -610,6 +623,23 @@ records, this path needs a locking test: record-as-last-field
round-trips, record-mid-struct is rejected (post-M1), and
`total_size` accounting for the prefix is asserted.
**Resolution (2026-09-02):** the requested locking tests, post-M1:
- `materialize.rs::materialize_aligned_record_last_field_roundtrips` —
`record<uint16>` as last field driven end-to-end through
`OffsetMap::compute` + `materialize_aligned`: both entries
materialize (`{ "b": 10, "a": 20 }`), `id` intact at its fixed
offset, wire arithmetic asserted in the test (22 bytes: 4 id + 4
record count + 2 × (4 key-len + 1 key + 2 value)).
- `engine.rs::validate_bytes_aligned_record_last_field_round_trips` —
the same shape through the full public `validate_bytes` path
(`record<uint32>`, 26 bytes), plus a corrupted-buffer arm asserting
garbage in entry bytes is rejected (not silently accepted).
- Post-M1 rejection covered by `non_final_record_rejected_in_aligned_mode`
(see M1's resolution); `total_size` prefix accounting asserted by
`final_inline_record_allowed_in_aligned_mode`.
Done with M1 + M3 in the same commit.
### M3. `read_field`'s aligned `Struct` arm is unreachable dead code
**File**: `src/engine.rs:449-452`
@@ -632,6 +662,20 @@ stage rather than at lookup), or keep it and make struct entries exist
(deliberate feature — then document and test it). Deleting is the
smaller, honest change for 0.3.0's design.
**Resolution (2026-09-02):** deletion taken. The `Struct` arm now
returns a documented defensive `Offset` error ("read_field does not
support composite types (no offset-map entry exists for a struct path —
only its leaf fields are recorded)") instead of a fabricated
`FieldValue::Struct` — the reachable failure for a struct path remains
the offset-map lookup miss, as the finding established. The doc comment
now states that struct paths have no `OffsetMap` entry (read the leaf
fields by dotted paths) and that the Offset miss is the reachable
failure for any composite path. Locking test
`read_field_on_nested_struct_path_is_offset_error_not_struct_value`:
`read_field("header")` is an `Offset` error while
`read_field("header.magic")` succeeds. `FieldValue::Struct` itself is
untouched (public API; still constructed by the packed reader).
### M4. Coverage weak spots map onto the findings above — the aligned materializer half is the least-tested code in the engine
**Tool**: `cargo llvm-cov --release` (0.8.4). Overall: **89.59% lines,
@@ -929,11 +973,15 @@ Worth recording, because the findings shouldn't eclipse it:
resolution block on the finding).
3. ~~**H2** — shared walk guard~~ **resolved 2026-09-02** (see the
resolution block on the finding).
4. **M1 + M2** — same file, same test family; do together.
5. **M3** — trivial deletion (or the feature decision, if kept).
4. ~~**M1 + M2**~~ **resolved 2026-09-02** (with M3; see the
resolution blocks on the findings).
5. ~~**M3**~~ **resolved 2026-09-02** (see the resolution block on the
finding).
6. **M4** — ongoing: per-fix coverage extension as recommended above;
the aligned-materializer test gap (1) is the single biggest chunk
and deserves its own session.
and deserves its own session. (M1/M2/M3's fixes each extended
coverage over their touched paths — the aligned record dispatch and
the aligned record `validate_bytes` path are now publicly exercised.)
7. **L1–L6, N1, N2** — opportunistic, folded into whichever session
touches the relevant file (L6 is the exception — it belongs with
H3; N2 pairs naturally with any bast/bast_meta session; L1 done