From 270f9d88b332566bef67c4f1bf4aeadfb7473c48 Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:50:54 -0700 Subject: [PATCH] audit: drop dead DTS marks cap, lazy passthrough buf, doc corrections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round-9 findings from the 10-phase release audit (no HIGH): - Remove the MAX_PTS_MARKS backstop and its tautological test: an empty DTS PES returns before recording a mark, and a non-empty run is already bounded by the MAX_AU_BYTES buffer clear (which clears pts_marks) — so the deque cannot grow unbounded and the cap was dead code. - AuAssembler::for_codec no longer reserves 256 KiB for a Passthrough stream (audio/subtitle, and every TS/BD stream) whose buf is never written; only the reassembling modes reserve. - Correct the scan comment that claimed region is computed (it is a Region-free stub until region detection lands) and drop a public-repo reference to internal "private refactor notes" in the mkb module doc. --- src/aacs/mkb.rs | 7 +++---- src/disc/mod.rs | 6 ++++-- src/mux/au_assembly.rs | 8 +++++++- src/mux/codec/dts.rs | 33 +++------------------------------ 4 files changed, 17 insertions(+), 37 deletions(-) diff --git a/src/aacs/mkb.rs b/src/aacs/mkb.rs index 2300c48..a6e017b 100644 --- a/src/aacs/mkb.rs +++ b/src/aacs/mkb.rs @@ -2,10 +2,9 @@ //! //! The MKB record format (framing walker, the `MkbRecord` view, record-body //! finders), the MKBType / AACS-generation classification, and MKB-file -//! utilities (content length, trimming, version). Consolidated here from the -//! former `keys.rs` / `variant.rs` so the one place that understands MKB bytes -//! is `mkb`. A follow-up collapses the remaining duplicate finders (see the -//! private refactor notes) — for now both dialects live here side by side. +//! utilities (content length, trimming, version). Consolidated here so the one +//! place that understands MKB bytes is `mkb`. Some duplicate record finders +//! still live side by side pending a follow-up that collapses them. // ── MKB record types ([C] Chapter 3) ────────────────────────────────────── // The ONE canonical set. Every record-type comparison in the `aacs` module diff --git a/src/disc/mod.rs b/src/disc/mod.rs index 808a1bd..701767a 100644 --- a/src/disc/mod.rs +++ b/src/disc/mod.rs @@ -1950,8 +1950,10 @@ impl Disc { crate::labels::apply(reader, &udf_fs, &mut titles); crate::labels::fill_defaults(&mut titles); - // 5. Format (AACS MKB generation → BD/UHD/FMTS; tree → HD-DVD/DVD), - // layers, region. + // 5. Format (AACS MKB generation → BD/UHD/FMTS; tree → HD-DVD/DVD) and + // layers. Region coding is not yet decoded from the disc — every disc + // reports Region-free for now (correct for all UHD; a stub for + // region-locked BD/DVD until region detection is implemented). let format = Self::detect_disc_format(reader, &udf_fs, &titles); let layers = if capacity > 24_000_000 { 2 } else { 1 }; let region = DiscRegion::Free; diff --git a/src/mux/au_assembly.rs b/src/mux/au_assembly.rs index 2c5022e..ecdfe85 100644 --- a/src/mux/au_assembly.rs +++ b/src/mux/au_assembly.rs @@ -142,7 +142,13 @@ impl AuAssembler { }; Self { mode, - buf: Vec::with_capacity(256 * 1024), + // Passthrough never writes `buf` (one fragment → one unit); only the + // reassembling modes need reserve. Avoids ~256 KiB per audio/subtitle + // stream (and every TS/BD stream, which never feeds the assembler). + buf: match mode { + Mode::Passthrough => Vec::new(), + _ => Vec::with_capacity(256 * 1024), + }, base: 0, marks: VecDeque::new(), disc_marks: VecDeque::new(), diff --git a/src/mux/codec/dts.rs b/src/mux/codec/dts.rs index 51063f7..ee74a03 100644 --- a/src/mux/codec/dts.rs +++ b/src/mux/codec/dts.rs @@ -140,12 +140,6 @@ impl DtsParser { /// this without a clean boundary we resync rather than stall or balloon. const MAX_AU_BYTES: usize = 65536; -/// Cap on buffered PTS marks. A real AU spans a few PES; this bounds the deque so -/// a run of zero-length timed PES packets (which grow no buffer bytes, so the -/// `drain_front` prune never fires) cannot accumulate marks without bound on -/// hostile program-stream input. -const MAX_PTS_MARKS: usize = 64 * 1024; - /// Number of leading bytes that must be buffered before the core `fsize` field /// (bytes 5-7) can be decoded. This is a HEADER-LAYOUT minimum — "enough bytes /// to read the size field" — and is deliberately distinct from @@ -236,15 +230,10 @@ impl CodecParser for DtsParser { // (see `front_pts`), so an AU whose core arrived in an earlier PES keeps // that core's timestamp even when its extensions / the following core // arrive (with a later PTS) in this same parse() call. + // (pts_marks is bounded implicitly: an empty PES returns above without + // pushing a mark, and a non-empty run grows `buf`, which is cleared — + // along with pts_marks — once it exceeds MAX_AU_BYTES.) self.pts_marks.push_back((self.buf.len(), pts_ns)); - // Backstop: a run of zero-length (sub-header-only) PES packets that each - // carry a PTS grows no buffer bytes, so `drain_front` (which prunes marks) - // never runs. Bound the deque directly — drop the oldest, which belongs to - // an already-emitted or lost AU — so hostile PS input can't accumulate - // marks without bound. - if self.pts_marks.len() > MAX_PTS_MARKS { - self.pts_marks.pop_front(); - } self.buf.extend_from_slice(&pes.data); let mut frames = Vec::new(); @@ -929,22 +918,6 @@ mod tests { assert_eq!(dts_core_sample_rate(&core), 48_000); } - #[test] - fn pts_marks_stay_bounded_on_zero_length_pes() { - // A run of zero-length (sub-header-only) DTS PES packets that each carry a - // PTS grows no buffer bytes, so drain_front (which prunes marks) never - // runs. The MAX_PTS_MARKS backstop must bound the deque regardless. - let mut parser = DtsParser::new(); - for i in 0..(MAX_PTS_MARKS * 2) { - parser.parse(&make_pes(Vec::new(), Some(i as i64))); - } - assert!( - parser.pts_marks.len() <= MAX_PTS_MARKS, - "pts_marks bounded, got {}", - parser.pts_marks.len() - ); - } - #[test] fn new_pes_rebases_to_its_own_pts_no_drift() { // Regression for the drift bug: a global running clock overshot a