Harden mux + decrypt paths; fail-loud on unresolvable keys
mp4 demuxer (untrusted input): bound every allocation sized from a box field (stsz/stco/stsc counts, stts/ctts run-lengths, per-sample and moov sizes, plus an absolute cap so a sparse file can't inflate file_len); guard the parse_stsd slice and a zero mdhd timescale; cap track count so the per-track PID can't overflow; rewrite read_moov to handle size==0 / size<8 / 64-bit largesize; parse esds/AudioSpecificConfig for AAC; write tkhd duration in the movie timescale. decrypt: resolve_mux_key_map now fails loud on an extent no key can classify instead of inheriting the previous extent's key, so a keymap never silently carries a wrong key; the sweep/patch key-fetch recovery fails loud when a unit is still unresolved after the retry. AACS: reject inverted forensic segments in both range builders; compare the forensic index in u16 space so an out-of-range value can't truncate onto a valid u8 index. RECOVERED_ERROR no longer latches the damage zone, preserving the 30s wedge cooldown for a following hard error. audio: AAC/MP2/MP3/FLAC carry the last PTS across a PES with no timestamp; the DTS-HD extension-sync search is bounded to after the core; the MP4 16.16 sample-rate field saturates. demux_sink records the video reference before the kind filter so audio:// / sub:// keep multi-clip PTS continuity and the DELAY tag. Remove a dead error variant and the AACS-unsupported-video code; codec comments cite the primary format specs; assorted doc/naming fixes and regression tests throughout.
This commit is contained in:
+5
-5
@@ -1867,7 +1867,7 @@ impl Disc {
|
||||
capacity: u32,
|
||||
handshake: Option<HandshakeResult>,
|
||||
handshake_error: Option<Error>,
|
||||
_opts: &ScanOptions,
|
||||
opts: &ScanOptions,
|
||||
udf_fs: udf::UdfFs,
|
||||
) -> Result<Self> {
|
||||
let scan_with_t0 = std::time::Instant::now();
|
||||
@@ -1931,7 +1931,7 @@ impl Disc {
|
||||
// forced flags match what the muxer derives during a rip (both use the
|
||||
// one shared PGS classifier); the rip path leaves it off — the muxer
|
||||
// detects forced while muxing, without a second read of the clip.
|
||||
if _opts.probe_forced_subtitles {
|
||||
if opts.probe_forced_subtitles {
|
||||
for title in &mut titles {
|
||||
if title.content_format == ContentFormat::BdTs {
|
||||
pgs_forced_probe::probe_and_set_forced(reader, title);
|
||||
@@ -2277,8 +2277,8 @@ impl std::fmt::Debug for Key {
|
||||
/// next candidate (and ultimately surfaces a key error rather than silently
|
||||
/// writing ciphertext).
|
||||
///
|
||||
/// Reuses the ecosystem's single `ts_sync_destroyed` predicate and the full
|
||||
/// (bus + AACS) unit decrypt, so it agrees with the actual mux decrypt.
|
||||
/// Reuses the ecosystem's single `is_clean` content-clarity predicate and the
|
||||
/// full (bus + AACS) unit decrypt, so it agrees with the actual mux decrypt.
|
||||
fn aligned_unit_keys_validate(
|
||||
unit_keys: &[(u32, [u8; 16])],
|
||||
read_data_key: Option<&[u8; 16]>,
|
||||
@@ -2367,7 +2367,7 @@ impl Disc {
|
||||
/// else (UDF filesystem, BDMV nav, PLAYLIST/CLIPINF) is always clear.
|
||||
///
|
||||
/// The in-read decrypt-verify gate (`DecryptingSectorSource`) uses this so it
|
||||
/// never consults [`ts_sync_destroyed`](crate::aacs::content::ts_sync_destroyed) about
|
||||
/// never consults the TS-sync content check about
|
||||
/// non-content bytes — filesystem data has no TS sync and would otherwise be
|
||||
/// mistaken for ciphertext (the first-2-GB false-positive this fixes).
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user