Audit round 2 fixes: an unsafe default, four omissions, and two swallowed errors
The folder encryption probe returned "not encrypted" when it had sampled nothing at all — a title shorter than one aligned unit skipped the loop entirely. That verdict CLEARS the structural one an AACS directory raised, so a genuinely encrypted folder would have been ripped as clear and written ciphertext as video at exit 0. With no evidence it now keeps the structural verdict, and its bounds arithmetic no longer trusts disc-derived values not to wrap. Reading an IFO header swallowed every I/O error and returned an empty buffer, which sent each placement offset through unwrap_or(0) and recorded no constraint at all — a permission error on one file produced a silently misplaced VOB. The directory walk swallowed the same class while claiming to skip only vanished files. Both now propagate; only NotFound is skipped. Four things the round-1 changes left inconsistent: two new error codes had no doc comments, were absent from the io::Error mapping, printed no path in Display, and were missing from the test that proves codes are distinct. The demux sink dropped frames silently while the MKV muxer reported them. And set_clips had been inserted INTO write_frame's doc comment, leaving write_frame undocumented and its paragraphs describing the wrong function. uid/gid used 0 as "not specified"; UDF's sentinel is 0xFFFFFFFF, and 0 is root.
This commit is contained in:
@@ -889,6 +889,18 @@ impl Stream for DemuxSink {
|
||||
return Ok(());
|
||||
}
|
||||
self.finished = true;
|
||||
// Same reporting as the MKV muxer's finish. Frames the playlist's clip
|
||||
// marks exclude are dropped on purpose, but the count must not be
|
||||
// write-only in one sink and reported in the other — an unexpected
|
||||
// volume here is how a demux ends up quietly short.
|
||||
let seam_dropped = self.timeline.dropped_total();
|
||||
if seam_dropped > 0 {
|
||||
tracing::info!(
|
||||
target: "mux",
|
||||
dropped = seam_dropped,
|
||||
"frames outside the playlist's clip marks were dropped at clip joins"
|
||||
);
|
||||
}
|
||||
// Flush each track's codec writer, then the buffered file.
|
||||
for slot in self.tracks.iter_mut() {
|
||||
if let Some(t) = slot.as_mut() {
|
||||
|
||||
+15
-16
@@ -1323,6 +1323,21 @@ impl<W: Write + Seek> MkvMuxer<W> {
|
||||
pub fn set_opening_capture(&mut self, capture: Option<crate::diag::OpeningCapture>) {
|
||||
self.opening_capture = capture;
|
||||
}
|
||||
/// Drive seam correction from the title's PlayItem marks instead of
|
||||
/// inferring it from PTS jumps.
|
||||
///
|
||||
/// A multi-clip Blu-ray playlist joins its clips with overlaps and skips
|
||||
/// that PTS inspection cannot recover: a forward jump is indistinguishable
|
||||
/// from frames lost to damaged media, and an overlap smaller than the
|
||||
/// reorder threshold is invisible. Given the marks, each clip is placed at
|
||||
/// the sum of the earlier clips' durations, so the output runs exactly as
|
||||
/// long as the playlist says the title is.
|
||||
///
|
||||
/// No-op for a title with fewer than two clips or without usable marks —
|
||||
/// DVD, HD-DVD and file sources keep the inference path.
|
||||
pub fn set_clips(&mut self, clips: &[crate::disc::Clip]) {
|
||||
self.continuity = TimelineContinuity::with_clips(clips);
|
||||
}
|
||||
|
||||
/// Write a single frame.
|
||||
///
|
||||
@@ -1349,22 +1364,6 @@ impl<W: Write + Seek> MkvMuxer<W> {
|
||||
/// BlockAdditional under the track's `mvcC` mapping. Such a frame is always a
|
||||
/// `BlockGroup` (never a SimpleBlock), with a `ReferenceBlock` when it is not
|
||||
/// a keyframe. `None` for every non-3D frame.
|
||||
/// Drive seam correction from the title's PlayItem marks instead of
|
||||
/// inferring it from PTS jumps.
|
||||
///
|
||||
/// A multi-clip Blu-ray playlist joins its clips with overlaps and skips
|
||||
/// that PTS inspection cannot recover: a forward jump is indistinguishable
|
||||
/// from frames lost to damaged media, and an overlap smaller than the
|
||||
/// reorder threshold is invisible. Given the marks, each clip is placed at
|
||||
/// the sum of the earlier clips' durations, so the output runs exactly as
|
||||
/// long as the playlist says the title is.
|
||||
///
|
||||
/// No-op for a title with fewer than two clips or without usable marks —
|
||||
/// DVD, HD-DVD and file sources keep the inference path.
|
||||
pub fn set_clips(&mut self, clips: &[crate::disc::Clip]) {
|
||||
self.continuity = TimelineContinuity::with_clips(clips);
|
||||
}
|
||||
|
||||
pub fn write_frame(
|
||||
&mut self,
|
||||
track_idx: usize,
|
||||
|
||||
Reference in New Issue
Block a user