Feed the CSS crack the canonical extent order, and stop Resolution faking 1080p
Seven defects in the code the test suite executes least — 913 lines of disc/mod.rs alone are run by no test at all, which is why this round scoped from coverage rather than from what previous rounds said they had read. Disc::scan_image kept its own copy of the crack's extent ordering and fed crack_key_outcome largest-cell-first. That is the fifth instance in this audit of a local reimplementation drifting from the canonical one, and the cost here is a key that does not descramble the feature: picking by sector count bypasses the capacity gate and can select a different VTS entirely. The copy is gone — which title comes from the canonical order the scan already applied, and the extents are handed over in playback order, exactly as decrypt_keys_for_title does. Its doc records why the duplicate existed so it cannot grow back. Resolution::pixels returned 1920x1080 for Unknown. That is the FOURTH instance of one trap and the other three were in this same file, two of them fixed hours earlier — without sweeping for siblings, which is the whole reason this one survived. It now returns (0, 0), and the sweep was done properly this time: every remaining Unknown arm across the crate is honest, and the two ColorSpace sites that look like fabrication are emitting H.273 code point 2, which is the spec's own "unspecified". Two callers carried local Unknown-to-zero workarounds — precisely the cost of making callers responsible for a lie — and one is now redundant. BD-ROM Part 3 code 0xA2 is the lossy secondary DTS stream, not lossless Master Audio. A test asserted the wrong mapping as intended behaviour, so correcting the code failed it; the test is deleted with a note pointing at its replacement. That is a NEW failure mode for this audit: not a test that cannot fail, but one that locks the defect in. There is no DtsExpress variant to map to, so it takes the lossy DTS-HD member and the approximation is documented. Also: DiscSession::identify could panic through drive_mut once the public API allows an absent drive — two siblings were converted in an earlier round and this one was missed; an extent end that added without saturating where the rest of the crate saturates; a diag reason string restating the comparator's sort keys and drifting from them, now derived from them; and a short read that advanced the offset by the full request, silently skipping the gap. That last one existed twice, in two reads with the same shape, now merged so they cannot drift apart. The short-read policy is a judgement call I could not derive from a spec: no skip_errors is a hard error, with skip_errors zero-fills and charges the loss. It deliberately does not retry mid-unit, because resuming inside an AACS aligned unit would trade a silent gap for a silent decrypt desync — the worse of the two.
This commit is contained in:
+31
-1
@@ -236,7 +236,16 @@ impl DiscSession {
|
||||
/// Fast disc identification — name/format only, no playlist parse. Wraps
|
||||
/// [`Disc::identify`].
|
||||
pub fn identify(&mut self) -> Result<DiscId> {
|
||||
Disc::identify(self.drive_mut())
|
||||
// Same reachability as `scan` / `resolve_keys` below: the PUBLIC
|
||||
// `stage_drive_as_reader` / `into_drive` move the drive out of the
|
||||
// session, so this slot can legitimately be empty when a caller reaches
|
||||
// here. A library must not panic from public API — going through
|
||||
// `drive_mut` would hit its `.expect("drive present")`. Return the same
|
||||
// typed `DeviceNotReady` its two siblings already do.
|
||||
let drive = self.drive.as_mut().ok_or_else(|| Error::DeviceNotReady {
|
||||
path: self.device.clone(),
|
||||
})?;
|
||||
Disc::identify(drive)
|
||||
}
|
||||
|
||||
/// Full structure scan. Forwards the session's [`KeySpec`] credentials /
|
||||
@@ -763,4 +772,25 @@ mod tests {
|
||||
"expected DeviceNotReady, got {err:?}"
|
||||
);
|
||||
}
|
||||
|
||||
/// `identify` after the drive has left the session (the PUBLIC
|
||||
/// `stage_drive_as_reader` / `into_drive` both permit that ordering) must
|
||||
/// return the typed `DeviceNotReady`, not reach `drive_mut`'s
|
||||
/// `.expect("drive present")` and panic. A library returns errors from its
|
||||
/// public API; only `main()` exits. This is the sibling of
|
||||
/// `scan` / `resolve_keys`, which were already converted.
|
||||
///
|
||||
/// Mutation: restore `Disc::identify(self.drive_mut())` → this test panics
|
||||
/// instead of receiving an `Err`.
|
||||
#[test]
|
||||
fn identify_without_a_drive_is_clean_device_not_ready() {
|
||||
let mut session = DiscSession::from_parts_for_test(None, None, None);
|
||||
let err = session
|
||||
.identify()
|
||||
.expect_err("identify without a drive must error, not panic");
|
||||
assert!(
|
||||
matches!(err, Error::DeviceNotReady { .. }),
|
||||
"expected DeviceNotReady, got {err:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user