Core hardening from the package audit: pull-block feasibility, real validation, resync clamp, C-ABI (PR A)#25
Merged
Merged
Conversation
F1 (High): pull blocks larger than the occupancy setpoint used to drain into a permanent underrun limit cycle (64-frame callbacks dropped out every ~0.24 s with defaults, never locking). pull() now raises the effective setpoint to the observed block plus sawtooth margin, bounded by FIFO capacity (auto-sized FIFOs get a 1024-frame floor so callbacks to ~340 frames work unconfigured); the servo slews to the new setpoint glitch-free and Status reports effectiveTargetLatencyFrames. Configs that already satisfied the constraint are byte-identical (icount within 0.07%, all targets). F2: validated() now rejects NaN/Inf config doubles (a NaN rate built an all-NaN coefficient table), band-edge sums above the rate (image passthrough), maxDeviationPpm beyond the Q0.64 int64 range (UB), and size products that wrap 32-bit size_t. F3: hard resync clamps the discard to ring contents (a setpoint below the staged scratch drained the ring and cascaded into Filling). C ABI: null-handle guards on every entry point, shipped srt_capi.h with the thread contract, srt_version() export. Sweeps: Q15 blend margin comment corrected (0.005%, not ~5%); estimateTaps clamps UB-range inputs; SpscRing asserts lock-free indices; stale planar/whitepaper/1 ms doc lines fixed; resampler preconditions and unfaded-cut honesty documented. Tests (+13): Feasibility 64/128/240 regression suite, validation throws, small-setpoint resync, consumer reset relock, zero-len and oversized calls, Q15 fade ramp, channels 5/7 (the K=2/K=1 channel-parallel tiles, previously uncovered), and QuickQuality - an emulation-sized Q15 SNR + near-full-scale gate that runs on the M33, M55 and Hexagon CI legs, which previously had no on-target SNR check. Host 64/64; M33 and M55 QEMU suites green. https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
tap
pushed a commit
that referenced
this pull request
Jun 12, 2026
The static-musl Hexagon toolchain cannot propagate C++ exceptions: the hardened validated() throws correctly but EXPECT_THROW never catches and libc++abi terminates - surfaced by the first throw-test ever to reach that CI leg (from PR #25, so main is currently red there; this commit heals it). Validation is target-independent and covered on every other platform. Limitation recorded in the Known-debt ledger with the deployment implication (invalid Config is fatal on this toolchain; validate before constructing) and the candidate fix (-unwindlib=libunwind). https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Audit fix series, part A — the product-correctness findings. (Part B, CI/infra hardening, lands separately; part C, the docs truth sweep, follows both.)
F1 (High): the pull-block feasibility bug — fixed with an adaptive setpoint
A pull must synthesize from frames already buffered, so any pull block larger than the occupancy setpoint made the configuration infeasible: with defaults, 64-frame callbacks dropped out every ~0.24 s forever (never Locked, ppm pegged at a false +1500); 240-frame callbacks emitted 80% silence. Now:
pull()raises the effective setpoint to the largest observed block + ~half-block sawtooth margin, bounded by FIFO capacity; the servo slews there glitch-free (integrator kept, occupancy only grows).fifoFrames(documented).Status::effectiveTargetLatencyFramesreports the setpoint in force;designedLatencySeconds()follows it. README latency section states the constraint plainly.Feasibility.Pull{64,128,240}LocksCleanly— the audit's exact failing scenarios, now asserting Locked / zero underruns / correct mean ppm / reported raise — plus a control that small pulls keep the configured setpoint.F2:
validated()actually validatesRejects NaN/Inf anywhere in Config (a NaN sample rate previously constructed an all-NaN-emitting converter), band-edge sums above the rate (anti-image cutoff past input Nyquist passed images wholesale),
maxDeviationPpmbeyond the Q0.64 int64 conversion range (UB before), and size products that wrap 32-bitsize_t. Boundary-tested:Config::forSampleRate(16k/44.1k)sit exactly on the band-edge-sum equality and must keep constructing.F3: resync over-discard
The hard-resync discard now clamps to ring contents; with a setpoint below the 16-frame staged scratch it used to drain the ring entirely and cascade straight back into Filling.
C ABI
Null-handle guards on every entry point (the "check create for NULL" convention previously crashed exactly the caller who forgot), a shipped
srt_capi.hcarrying the thread contract, andsrt_version().Sweeps + tests
Comment-arithmetic corrections (Q15 blend margin is 0.005%, not ~5%; Config's "~1 ms" was 1.5 ms),
estimateTapsUB clamp,SpscRinglock-free static_assert, stale planar/whitepaper doc lines, resampler preconditions and the unfaded-cut honesty note. 13 new tests including channels 5/7 (the only counts reaching the channel-parallel K=2/K=1 remainder tiles — previously zero coverage) and QuickQuality: an emulation-sized Q15 SNR + near-full-scale saturation gate that runs on the M33/M55/Hexagon CI legs, which previously had no on-target SNR check at all.Verified: host 64/64 under
-Werror; M33 (171 s) and M55 (20 s) QEMU suites green; C-ABI builds; long new float sims excluded from emulated targets by filter/regex (checked against both mechanisms).https://claude.ai/code/session_01HuAFfoeD5a5Xe5aGNA16M9
Generated by Claude Code