libvorbis+libopus: 5-MOAD scan; CLEAN both targets

This commit is contained in:
russell@unturf.com 2026-03-31 22:38:59 -04:00
parent 8a3fc56b23
commit 2c215e46e5
2 changed files with 163 additions and 0 deletions

View file

@ -0,0 +1,85 @@
# libopus (Opus audio codec) — 5-MOAD Scan Result: CLEAN
**Target:** xiph/opus
**Source:** https://github.com/xiph/opus
**Scan Date:** 2026-03-31
**Language:** C
---
## MOAD-0001 — CWE-407: Algorithmic Complexity (list membership in loop)
### Candidates investigated
**`silk/sort.c``silk_insertion_sort_increasing_all_values_int16()` (lines 147153)**
Insertion sort O(L²) worst case. L = LPC order, which is spec-fixed: 10 (NB/MB)
or 16 (WB). Max 256 comparisons per call. Called only in `silk_NLSF_stabilize`
fallback path when iterative adjustment exceeds MAX_LOOPS=20, which is itself a
rare corner case. Bounded absolutely. Not actionable.
**`silk/NLSF_stabilize.c` — main loop (lines 60118)**
Outer loop over MAX_LOOPS=20 iterations. Inner loops over L (10 or 16) elements
for min-diff search, plus two accumulation loops over k<I and k>I (up to L).
Total: O(20 × L) = O(320) ops worst case. Spec-bounded. CLEAN.
**`silk/NLSF_VQ.c``silk_NLSF_VQ()` codebook search (lines 5475)**
O(K × LPC_order) where K=nVectors. Both codebooks (WB and NB/MB) have K=32
and LPC_order of 16 or 10. Max 512 ops per call. Spec-bounded. CLEAN.
**`silk/NLSF_encode.c``silk_insertion_sort_increasing()` on K=32 errors (line 75)**
Partial insertion sort to find nSurvivors best candidates from 32. K=32 is
spec-fixed. CLEAN.
**`src/opus_multistream.c``get_left_channel()` / `get_right_channel()` / `get_mono_channel()` (lines 5791)**
Per-frame call inside the outer `for(s=0; s<nb_streams; s++)` decode loop.
Each `get_*_channel` call scans `nb_channels` (max 255 per spec). Total:
O(nb_streams × nb_channels) = O(255×255) = ~65000 per decode call. However:
(a) these functions advance via `prev` parameter — no restart scanning; the
while loop in the decoder iterates each channel at most once per stream,
making the total across all streams O(nb_channels), not O(S×C). (b) Practical
multistream configs are 28 channels, 14 streams. Not a growth defect. CLEAN.
**`celt/bands.c` — all band processing loops**
All loops are bounded by `eBands` entries (21 for CELT wideband) and
`nb_channels` (12 in typical operation). No nested membership test pattern.
CLEAN.
### Verdict: CLEAN — no CWE-407 defects
---
## MOAD-0002 — Intertangle: shared mutable global state / god object
No mutable process-global state in encode/decode paths. All session state lives
in `OpusEncoder`, `OpusDecoder`, `SilkEncoder`, `SilkDecoder` structs allocated
and owned by callers. No static mutable globals found in `silk/`, `celt/`, or
`src/` encode/decode paths. CLEAN.
---
## MOAD-0003 — Leaked Context: ThreadLocal / thread-scoped request identity
No `pthread_getspecific`, `__thread`, `thread_local`, or equivalent in any C
source under `silk/`, `celt/`, or `src/`. Pure C library with caller-owned state.
CLEAN.
---
## MOAD-0004 — CWE-312: credentials or keys logged verbatim
Pure audio codec library. No auth flows, HTTP headers, API keys, or credential
handling. CLEAN.
---
## MOAD-0005 — Thundering Herd: unsynchronized cache get+null+compute+put
No shared cache with double-checked locking or unsynchronized lazy initialization
in encode/decode paths. `silk_NLSF_stabilize` memo state is stack-local. CELT
mode tables are `static const` (read-only). CLEAN.

View file

@ -0,0 +1,78 @@
# libvorbis (Ogg Vorbis) — 5-MOAD Scan Result: CLEAN
**Target:** xiph/vorbis
**Source:** https://github.com/xiph/vorbis
**Scan Date:** 2026-03-31
**Language:** C
---
## MOAD-0001 — CWE-407: Algorithmic Complexity (list membership in loop)
### Candidates investigated
**`lib/floor1.c``floor1_look()` neighbor search (lines 233252)**
Double loop: outer over `n-2` posts (n ≤ VIF_POSIT+2 = 65), inner over `i+2`
prior posts. O(n²) = O(63²) = ~3969 ops. Runs once per codec setup call, not
per frame. Bounded absolutely by spec constant VIF_POSIT=63. Not actionable.
**`lib/res0.c``_01class()` / `_2class()` partition threshold scan (lines 441444, 505508)**
For each partition value, a linear scan through `possible_partitions` to find
our threshold bracket. Outer loop is over `partvals` (n/grouping, where n is
residue length and grouping is typically 32). Inner scan is at most
`possible_partitions-1` ≤ 63 (6-bit field per spec). Both dimensions are
codec-spec bounded. In practice: 64 partvals × 63 partitions = 4032 comparisons
per frame. Not an O(N²) growth pattern over user-controlled input. Not actionable.
**`lib/psy.c``noise_normalize()` qsort call**
Sorts up to `n` floats per partition band. Uses qsort (O(n log n)). CLEAN.
**`lib/floor1.c` — per-frame `floor1_forward_block()` neighbor update (lines 680689)**
Two inner loops over `posts` positions when a new split post is accepted. Both
break immediately on first mismatch — amortized O(posts) total across all splits
per frame. Not O(posts²). CLEAN.
**`lib/vorbisfile.c` — serialno scan (lines 840841, 13731374)**
Linear scan of `vf->serialnos[link]` inside page-reading loop. `vf->links` is
the number of chained bitstreams in the file — typically 13 for real files.
Seek-path only, not hot decode path. CLEAN.
### Verdict: CLEAN — no CWE-407 defects
---
## MOAD-0002 — Intertangle: shared mutable global state / god object
No mutable process-global state in the encode/decode path. All per-session state
lives in `vorbis_dsp_state`, `vorbis_block`, `vorbis_info` — caller-owned structs.
`lib/misc.c` global tracking (`pointers`, `global_bytes`) is `#ifdef DEBUG_MALLOC`
only — not compiled in production. `mapping0.c` `seq`/`total` statics are inside
`#if 0` dead code block. CLEAN.
---
## MOAD-0003 — Leaked Context: ThreadLocal / thread-scoped request identity
No `pthread_getspecific`, `__thread`, `thread_local`, or equivalent in any
encode/decode path. Pure C library with caller-owned state. CLEAN.
---
## MOAD-0004 — CWE-312: credentials or keys logged verbatim
Pure audio codec library. No auth flows, HTTP headers, API keys, or credential
handling anywhere in our codebase. CLEAN.
---
## MOAD-0005 — Thundering Herd: unsynchronized cache get+null+compute+put
No caching with unsynchronized double-checked access. `lib/floor0.c`/`floor1.c`
memo arrays are stack-local per-block, passed explicitly. `lib/smallft.c`
trigcache is computed once during `drft_init` in single-threaded setup, never
updated after initialization. CLEAN.