Audit round 1 fixes: sparse-track joins, silent drops, and two encoder wraps

A sparse passive track — a subtitle with no event near a clip's mark —
was held to the dense-video crossing window, so it stayed on the previous
clip's offset until its PTS passed that clip's OUT and every event in
between was mistimed by the overlap. Video keeps the tight window,
because its backward steps are also B-frame reorder; passive tracks have
no reorder, so any backward step into the next clip's range is a join.

Frames the marks exclude were dropped without a trace. Dropping is right
at a join, but this codebase has shipped complete-looking wrong output
before, so the count is kept per track and reported when the mux
finishes, alongside the pre-cluster counter that exists for the same
reason.

A File Identifier Descriptor records its name length in one byte, and the
length was narrowed with a cast: a 255-byte name — POSIX NAME_MAX,
entirely ordinary — encodes to 256 and wrote zero, which would read every
later entry in that directory from the wrong offset. A directory's link
count is 16 bits and was computed as 1 + subdirectory count, which the
global entry cap alone permits overflowing. Both are refused while
planning, where the tree can still be rejected cleanly.

The module and struct docs described inference as the whole algorithm;
they now say which path decides what.
This commit is contained in:
Matthew Jackson
2026-08-05 16:58:49 -07:00
parent 9247e7da2f
commit ffbc1d8399
5 changed files with 386 additions and 32 deletions
+23
View File
@@ -195,6 +195,8 @@ pub const E_DIR_IMAGE_FILE_CHANGED: u16 = 9065;
/// A `dir://` SOURCE folder does not fit a 32-bit sector address space
/// (> 2^32 sectors ≈ 8 TiB), or holds more entries than a UDF tree can carry.
pub const E_DIR_IMAGE_TOO_LARGE: u16 = 9066;
pub const E_DIR_NAME_TOO_LONG: u16 = 9067;
pub const E_DIR_IMAGE_FANOUT: u16 = 9068;
pub const E_M2TS_PACKET_MALFORMED: u16 = 9021;
/// A `network://` output target resolved to no address that is safe to
/// connect to (every resolved IP was loopback / private / link-local /
@@ -777,6 +779,25 @@ pub enum Error {
},
/// A `dir://` SOURCE folder exceeds the addressable image size.
DirImageTooLarge,
/// A name is too long to record in a UDF directory entry.
///
/// The File Identifier Descriptor stores the encoded name length in ONE
/// byte, so a name whose OSTA CS0 encoding exceeds 254 bytes cannot be
/// described. Truncating the length field instead would desynchronise the
/// whole directory — every later entry in it would be read from the wrong
/// offset — so an over-long name is refused while the tree is still being
/// planned.
DirNameTooLong {
path: String,
},
/// One directory holds more subdirectories than a UDF link count can express.
///
/// A directory's File Entry records its link count in 16 bits, and that
/// count is one per child directory plus one for its own entry in its
/// parent. Beyond that the count silently wraps, so the tree is refused.
DirImageFanout {
path: String,
},
}
impl Error {
@@ -898,6 +919,8 @@ impl Error {
Error::DirImagePlacement { .. } => E_DIR_IMAGE_PLACEMENT,
Error::DirImageEncrypted => E_DIR_IMAGE_ENCRYPTED,
Error::DirImageUnsupportedTree => E_DIR_IMAGE_UNSUPPORTED_TREE,
Error::DirNameTooLong { .. } => E_DIR_NAME_TOO_LONG,
Error::DirImageFanout { .. } => E_DIR_IMAGE_FANOUT,
Error::DirImageFileChanged { .. } => E_DIR_IMAGE_FILE_CHANGED,
Error::DirImageTooLarge => E_DIR_IMAGE_TOO_LARGE,
}