Skip to content

Commit 8186f8a

Browse files
author
crispasr integration
committed
plan: stb_vorbis heap overflow DONE (2d2c13e); claim removed
Per this file's own rule, the claim block goes when the work lands. Records what is left: reporting the int truncation upstream to nothings/stb, which still has it.
1 parent 2d2c13e commit 8186f8a

1 file changed

Lines changed: 30 additions & 69 deletions

File tree

PLAN.md

Lines changed: 30 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -827,75 +827,36 @@ second is small and unbreaks the platform immediately.
827827
Found while reproducing #369, and NOT that issue's cause: the reporter is on
828828
Windows CPU/Vulkan and sees wrong-language output, not silence.
829829

830-
## CLAIMED 2026-09-07 — stb_vorbis heap overflow (security), root cause found
831-
832-
Worktree: main (`/mnt/volume1/CrispASR`). Taking the OPEN item below.
833-
834-
ROOT CAUSE, confirmed by arithmetic against the ASAN report, not inferred:
835-
836-
f->comment_list_length = get32_packet(f); // attacker uint32
837-
f->comment_list = setup_malloc(f, sizeof(char*) * f->comment_list_length);
838-
memset(f->comment_list, 0, sizeof(char*) * f->comment_list_length);
839-
840-
`setup_malloc(vorb *f, int sz)` takes an **int**. With length = 1646854400,
841-
`8 * length` = 13,174,835,200 truncates to **289,933,312** — exactly the
842-
allocation size ASAN reported. The `memset` computes the same product but
843-
`sizeof` makes it `size_t`, so it is **13,174,835,200** — exactly the write size
844-
ASAN reported. THE ALLOCATION TRUNCATES AND THE CONSUMER DOES NOT. Same shape as
845-
the `resample_polyphase` n_out overflow fixed 2026-09-04 (int guard over a value
846-
that had already wrapped).
847-
848-
UPSTREAM HAS NOT FIXED IT (checked, per the next-steps note below):
849-
nothings/stb master still has `setup_malloc(vorb *f, int sz)` and the same
850-
truncating multiply. So there is nothing to pull, the vendored patch is correct,
851-
and upstream is vulnerable by the same truncation — it lacks our `memset`, so
852-
instead of one 13 GB write its `for` loop walks `comment_list[i]` past the short
853-
allocation. Worth reporting upstream once ours is fixed.
854-
855-
NOTE the memset is itself a CrispASR patch, added to fix an earlier fuzz crash
856-
(NULL comment_list freed by vorbis_deinit). It did not create the truncation, but
857-
it converted a gradual overflow into an immediate 13 GB one.
858-
859-
Plan: bound `comment_list_length` before allocating so the product cannot
860-
truncate, size the allocation in `size_t`, craft a minimal Ogg reproducer into
861-
`tests/fuzz/regressions/` (which now actually replays — the copy step counts its
862-
seeds since 2026-09-04), and let `linux-fuzz-smoke` be the gate.
863-
864-
## OPEN 2026-08-18 — stb_vorbis heap overflow on untrusted audio (security)
865-
866-
Found incidentally by `linux-fuzz-smoke` on PR #371, which does not touch that
867-
code — fuzzing is stochastic and it happened to surface there. NOT that PR's
868-
fault, and it reproduces from the audio fuzzer, not from anything in the diff.
869-
870-
==6684==ERROR: AddressSanitizer: heap-buffer-overflow
871-
WRITE of size 13174835200 at 0x7f29bad7d000
872-
#0 memset
873-
#1 start_decoder(stb_vorbis*) examples/stb_vorbis.c:3683
874-
#2 stb_vorbis_open_memory examples/stb_vorbis.c:5141
875-
#3 stb_vorbis_decode_memory examples/stb_vorbis.c:5419
876-
#4 crispasr_webm_decode(...) src/crispasr_audio.cpp:1405
877-
#5 crispasr_audio_load src/crispasr_audio.cpp:2801
878-
#6 LLVMFuzzerTestOneInput tests/fuzz/fuzz_audio_load.cpp:40
879-
880-
0x7f29bad7d000 is located 0 bytes after a 289933312-byte region
881-
allocated by setup_malloc(stb_vorbis*, int) examples/stb_vorbis.c:960
882-
883-
A 13 GB `memset` past a 289 MB allocation: the size computation in
884-
`start_decoder` overflows or is not validated against the allocation
885-
`setup_malloc` actually made. Reachable through `crispasr_audio_load`, i.e. on
886-
ANY caller-supplied audio file — the CLI, the HTTP server's upload path, and
887-
every binding. That makes it a memory-safety issue on untrusted input, not just
888-
a fuzz curiosity.
889-
890-
Severity note, honestly: a 13 GB write will fault almost immediately in
891-
practice, so the realistic outcome is a crash (DoS) rather than exploitable
892-
corruption. Worth fixing regardless, and worth checking whether a smaller,
893-
more controllable overflow is reachable from the same path.
894-
895-
Next steps: reproduce locally with a fuzz build
896-
(`-DCRISPASR_FUZZ=ON -DCRISPASR_SANITIZE_ADDRESS=ON`), minimise the input, then
897-
decide between bounds-checking `start_decoder` and pulling a newer stb_vorbis.
898-
Check whether upstream stb has already fixed it before patching a vendored copy.
830+
## DONE 2026-09-07 — stb_vorbis heap overflow on untrusted audio (security)
831+
832+
OPEN since 2026-08-18; fixed in `2d2c13ee`. Reachable from `crispasr_audio_load`
833+
— CLI, server upload, every binding.
834+
835+
`setup_malloc` takes an **int**, so `sizeof(char*) * comment_list_length`
836+
truncated 13,174,835,200 to 289,933,312 and allocated that, while the `memset`
837+
on the next line computed the same product in `size_t` and wrote the full 13 GB.
838+
Both numbers match the original ASAN report exactly. One quantity, computed two
839+
ways, disagreeing across a boundary — the same shape as the
840+
`resample_polyphase` `n_out` overflow fixed 2026-09-04.
841+
842+
Upstream nothings/stb has NOT fixed it (checked, as the item asked): master
843+
still carries the int-typed `setup_malloc` and the same multiply, so there was
844+
nothing to pull, and upstream is vulnerable by the same truncation. Worth
845+
reporting there — not yet done.
846+
847+
Fixed at the call site (bound the count before the multiply: no truncation, and
848+
at most `stream_len/4` comments since each costs 4 bytes for its own length
849+
field) and at the choke point (`setup_malloc` rejects a negative `sz`). The
850+
vendor and per-comment strings on the same path got the same data-derived bound.
851+
852+
`tests/fuzz/regressions/ogg-comment-count-int-overflow.ogg` (101 bytes,
853+
generated by `tools/gen-ogg-comment-fuzz-seed.py`) reproduces the original
854+
report exactly against the pre-fix decoder — same write size, same region size,
855+
same four stack frames and line numbers — and is clean after. The corpus
856+
README's previously-missing seed value (`0x3FFFFFFF`) was generated and tested
857+
and reproduces nothing today, so that row is retired rather than restored.
858+
859+
REMAINING, small: report the truncation upstream to nothings/stb.
899860

900861
## Start here
901862

0 commit comments

Comments
 (0)