From cf729275276442878b3bdf45d5d3ea71fa497892 Mon Sep 17 00:00:00 2001 From: Matthew Jackson <1085847+MattJackson@users.noreply.github.com> Date: Wed, 19 Aug 2026 10:06:52 -0700 Subject: [PATCH] Strip a trailing ; comment on M/I/V keydb fields, not just U MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit parse_disc_entry's U arm stripped a `; MKBv…` comment before hex-parsing the value, but the M/I/V arms did not. When a real keydb.cfg disc row's LAST field is M/I/V (no U after it), the comment glues onto that value and parse_hex16 of "0x… ; MKBv64" fails — silently dropping a media/id/VUK key the file actually holds, so the disc reports no key. Strip the comment in M/I/V too (a hex16 never contains ';', so it is safe), with a red-before-green regression test. --- src/keydb_format.rs | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/keydb_format.rs b/src/keydb_format.rs index b89cc71..359ed03 100644 --- a/src/keydb_format.rs +++ b/src/keydb_format.rs @@ -882,21 +882,28 @@ impl KeyDb { let mut i = 1; while i < parts.len() { match parts[i].trim() { + // M/I/V strip a trailing `; comment` before hex-parsing, exactly + // as the U arm below does: when the disc row's LAST field is one + // of these (no U field after it), a real keydb.cfg glues the + // `; MKBv…` comment onto that value, and parse_hex16 of + // "0x… ; MKBv64" fails — silently dropping a key the file + // actually holds. A hex16 never contains ';', so the split is safe. "M" => { if i + 1 < parts.len() { - media_key = parse_hex16(parts[i + 1].trim()); + media_key = + parse_hex16(parts[i + 1].split(';').next().unwrap_or("").trim()); i += 1; } } "I" => { if i + 1 < parts.len() { - vid = parse_hex16(parts[i + 1].trim()); + vid = parse_hex16(parts[i + 1].split(';').next().unwrap_or("").trim()); i += 1; } } "V" => { if i + 1 < parts.len() { - vuk = parse_hex16(parts[i + 1].trim()); + vuk = parse_hex16(parts[i + 1].split(';').next().unwrap_or("").trim()); i += 1; } } @@ -1152,6 +1159,25 @@ mod tests { assert_eq!(entry.unit_keys[0].0, 1); } + #[test] + fn disc_entry_strips_a_comment_glued_to_a_trailing_v_field() { + // A real keydb.cfg row whose LAST field is V (no U after it) with the + // `; MKBv…` comment glued straight onto the hex value. The U arm already + // strips such a comment; before M/I/V did too, parse_hex16 saw + // "0x00… ; MKBv64" and silently dropped the VUK — the disc then reported + // no key despite the file holding one. + let z40 = "00".repeat(20); + let z32 = "00".repeat(16); + let line = + format!("0x{z40} = SAMPLE (Sample) | M | 0x{z32} | I | 0x{z32} | V | 0x{z32} ; MKBv64"); + let entry = KeyDb::parse_disc_entry(&line).unwrap(); + assert!(entry.media_key.is_some(), "M key must survive"); + assert!( + entry.vuk.is_some(), + "a VUK with a trailing ; comment must not be dropped" + ); + } + // NOTE: key fields below use obvious repeated-byte / zero placeholders // (0x01.., 0x02.., 0x03.., 0x00..). NEVER put real — or real-looking — host, // device, or processing key material in code; these tests exercise the