diff --git a/CHANGELOG.md b/CHANGELOG.md index f5411ee..a3cf9a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,49 @@ All notable changes to this crate are documented here. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this crate adheres to [Semantic Versioning](https://semver.org/). +## [0.4.0] - 2026-09-30 + +The fuzzing release. The fuzz/ workspace (docs/plans/fuzzing.md) put +five libFuzzer targets on the engine — bast_compile, data_access, +read_opseq, layout_build, validate_pair — with release-budget campaigns +across all five. Two genuine engine bugs found and fixed same-day, +plus one upstream pin (docs/plans/fuzzing.md §6, §5 campaign numbers). + +### Breaking changes + +- **`VariableEncoding` gains `MaxLengthReserved`** (finding W3-3): + the aligned-mode `maxLength` reservation (ADR-003 strategy 2, the + `VARCHAR(N)` pattern) is now recorded as its own encoding variant + instead of masquerading as `LengthPrefixed`. Code matching on + `VariableEncoding` exhaustively must add an arm; in the document + form the strategy is still expressed via `maxLength`, never as an + `encoding` value. +- **`read_field`/`write_field` fix for aligned `maxLength` + reservations** (finding W3-3, commit `a0dd3d2`): an aligned + String/Bytes leaf with a declared `maxLength` is now read as a raw + zero-padded, NUL-trimmed window and written zero-padded — previously + the first four raw bytes of the reservation window were misparsed as + a u32 length prefix, breaking the validate_bytes ⇒ read_field + agreement for every aligned schema declaring `maxLength`. +- **`plan_read_array` bounds check** (finding W2-1, wave 2): a + fixed-stride array whose declared window (count × stride) extends + past the buffer now returns an `Access` error naming the array + field instead of reporting success and deferring the failure to the + next field read (or masking it entirely when the array was last). + +### Additions + +- **`data_access::read_reservation` / `read_reservation_string` / + `write_reservation`** — the single source of truth for the + `maxLength` reservation leaf semantics, shared with the aligned + materializer. +- **`fuzz/` subtree** — five libFuzzer targets, 257 committed seeds, + the corpus-replay gate (`cargo test --manifest-path + fuzz/shared/Cargo.toml`, AGENTS.md verification checklist), the + detached campaign runner; nightly confined to `fuzz/`, `fuzz/` + excluded from the package. All targets, seeds, and the replay gate + are stable-toolchain safe. + ## [0.3.0] - 2026-09-07 The compiled-forms release. The packed read path — the hot path for diff --git a/Cargo.lock b/Cargo.lock index 166d67d..f84d24e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "alktype" -version = "0.3.0" +version = "0.4.0" dependencies = [ "criterion", "jsonschema", diff --git a/Cargo.toml b/Cargo.toml index 4387eff..757c93c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alktype" -version = "0.3.0" +version = "0.4.0" edition = "2021" rust-version = "1.85" license = "MIT OR Apache-2.0" diff --git a/fuzz/Cargo.lock b/fuzz/Cargo.lock index 3014b5f..887270b 100644 --- a/fuzz/Cargo.lock +++ b/fuzz/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "alktype" -version = "0.3.0" +version = "0.4.0" dependencies = [ "jsonschema", "serde_json",