From dbafbf52bc778cd131e37bd8eee60a06a7cf8902 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 14 Oct 2026 20:57:58 +0200 Subject: [PATCH] cultcache-rs docs: state the decoder's fixed stack floor, record the Windows run The README and decode_payload claimed the calling thread needs only its own frames. Measured, the door has a payload-independent floor (release 56 KiB vs 16 for a same-signature non-decoding function; debug 104 vs 88). Say so, and replace "Windows not yet verified" with the one by-hand Starfire run of decode_stack on x86_64-pc-windows-msvc. Co-Authored-By: Claude Sonnet 5.5 --- packages/cultcache-rs/README.md | 7 +++++-- packages/cultcache-rs/src/lib.rs | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/cultcache-rs/README.md b/packages/cultcache-rs/README.md index 9b017ce1..2d1fa671 100644 --- a/packages/cultcache-rs/README.md +++ b/packages/cultcache-rs/README.md @@ -470,8 +470,11 @@ The guarantee holds for records the derives produce. `MAX_RECORD_INLINE_BYTES` record may have, and the derives refuse a larger one at compile time: put its large data behind a `Vec` or a `Box`. A field of a type the derives did not produce that is larger than that, behind a `Box` or `Vec`, is outside the -guarantee. The caller's thread needs only its own frames, which hold the -returned value. Stack growth on Windows is not yet verified. The crate does not +guarantee. The decoder's own frames have a fixed floor that no payload changes: at the bound a thread decodes a record of +this size from about 56 KiB in a release build and 104 KiB in a debug build, against 16 and 88 KiB for a function +of the same signature that decodes nothing, plus the caller's own frames. Stack growth was verified on +x86_64-pc-windows-msvc once, by hand, on Starfire (`decode_stack`, debug and release); later `stacker` bumps repeat it. +The crate does not build for wasm32 (`fs2`), and no wasm behaviour is claimed. ### Build dependencies diff --git a/packages/cultcache-rs/src/lib.rs b/packages/cultcache-rs/src/lib.rs index 2c34d260..4714ab79 100644 --- a/packages/cultcache-rs/src/lib.rs +++ b/packages/cultcache-rs/src/lib.rs @@ -704,9 +704,11 @@ fn decode_grown(bytes: &[u8]) -> std::result::Re /// rmp-serde depth counter (1024) is only a backstop. A failure keeps its kind and never quotes the /// bytes. Readers of stored envelope payloads outside this crate decode through it too. /// -/// A payload inside the bound decodes whatever the calling thread's stack: the thread needs only its -/// own frames that hold the returned value. That holds for every record the derives produce, which -/// [`MAX_RECORD_INLINE_BYTES`] bounds; Windows stack growth is not yet verified. +/// A payload inside the bound decodes on any thread that has the decoder's fixed floor, which no payload +/// changes: at the bound, about 56 KiB in release and 104 KiB in debug, against 16 and 88 KiB for a +/// same-signature function that decodes nothing, plus the caller's own frames. That holds for every +/// record the derives produce, which [`MAX_RECORD_INLINE_BYTES`] bounds. Stack growth was verified on +/// Windows once, by hand; a `stacker` bump repeats it. pub fn decode_payload(payload: &[u8]) -> Result { check_payload_depth(payload)?; decode_grown(payload).map_err(opaque_decode_error)