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:
1 parent
5e74b991ac
commit
dcfe9d16ff
4 files changed
+247
-17
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user