Stop reporting an uncrackable CSS disc as N empty titles
Same shape as the mkv:// conflation fixed earlier in this round, found by looking for it deliberately. E7023 carried two conditions with opposite correct responses: one title on a multi-VTS DVD failing its own re-crack, where skipping it and finishing the rest is right, and the main feature's crack failing outright, which is disc-wide and dooms every title identically. Because both raised the same code and that code is in is_skippable_title_stub, an uncrackable disc walked all N titles printing "title skipped, it was empty" and exited 0. The disc-wide condition gets E7027 CssNoDiscKey, mirroring the AACS-side E7022 NoDiscKey it is the analogue of, and joins is_disc_level_no_key. The per-title raise keeps E7023 and stays skippable. Because the engine's classifier already tests is_disc_level_no_key before the skippable branch, this reaches the right outcome downstream with no change there: such a disc now stops on the first title and reports no-key instead of returning success with nothing written. Disc::css_error deliberately still stores CssKeyMissing — autorip matches that variant on the field to pick the CSS rather than AACS message, and what consumers classify on is the gate's returned verdict, which is the only thing that changed. Two neighbouring CSS raises were examined and deliberately left alone: the no-key branch in the same function is genuinely unreachable via ensure_decryptable and documented as defensive, and resolve_dvd_title_key is per-title on both of its call paths. Verified by removing the new code from is_disc_level_no_key, which fails both new tests; each pins both directions so neither can silently flip. Not proven end to end against a real uncrackable disc — none available.
This commit is contained in:
+11
-3
@@ -91,8 +91,11 @@ pub fn crack_key(
|
||||
/// key could be recovered (the Stevenson attack found no crackable crib, or
|
||||
/// the scrambled region was unreadable). The content is encrypted; muxing it
|
||||
/// as plaintext would emit garbage, so callers MUST surface a hard error
|
||||
/// ([`crate::error::Error::CssKeyMissing`]) instead of falling through to
|
||||
/// "unencrypted".
|
||||
/// instead of falling through to "unencrypted" — the per-title
|
||||
/// [`crate::error::Error::CssKeyMissing`] when it is ONE title's own re-crack
|
||||
/// that failed (skippable: a sibling VTS may still crack), or the disc-level
|
||||
/// [`crate::error::Error::CssNoDiscKey`] when it is the disc-wide scan
|
||||
/// (`Disc::css_error`, every title fails identically).
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum CrackOutcome {
|
||||
Cracked(CssState),
|
||||
@@ -148,7 +151,12 @@ pub fn crack_key_outcome(
|
||||
/// - a genuinely clear DVD (no scrambled sector) — stays `None`, a mux no-op.
|
||||
///
|
||||
/// A scrambled-but-uncrackable title is a hard [`crate::error::Error::CssKeyMissing`],
|
||||
/// never a silent scrambled-passthrough mux.
|
||||
/// never a silent scrambled-passthrough mux. That code is the PER-TITLE one
|
||||
/// (`error::is_skippable_title_stub`), which is correct here: this function
|
||||
/// cracks ONE title's own extents, and another VTS on the same disc may still
|
||||
/// yield its key, so an all-titles rip skips this title and finishes the rest.
|
||||
/// The whole-disc failure is [`crate::error::Error::CssNoDiscKey`], raised by
|
||||
/// `Disc::ensure_decryptable_keys` from the scan's `css_error`.
|
||||
pub(crate) fn resolve_dvd_title_key(
|
||||
reader: &mut dyn SectorSource,
|
||||
extents: &[Extent],
|
||||
|
||||
Reference in New Issue
Block a user