Audit fixes + DVD support foundation (IFO, PS demux, MPEG-2, CSS crack)

Audit fixes (14 critical, 22 warnings):
- UDF: bounds checks on all ICB/FID parsing from disc data
- SCSI Linux: saturating_sub on residual, CDB length guard, buffer size guard
- SCSI macOS: SCSITaskStatus u32 (was u8 — stack corruption)
- AACS: EC mod_inv returns infinity instead of panic, key reduced mod n
- AACS: do_handshake tries all host certs (was returning on first failure)
- H.264: bounds check on SPS < 4 bytes
- ContentReader: error on missing unit key (was zero-fill)
- KEYDB: flat redirect loop (was recursive), 100MB response limit, Windows HOME fallback
- ISO writer: AVDP extent order, partition length, allocation cap
- Network: removed TCP_NODELAY on bulk stream
- MKV: guard on u64::MAX seek
- disc.rs: saturating_sub on extent offset, simplified dead region code
- cargo fmt (610 violations), cargo clippy --fix (55 auto-fixes)

DVD support (new files):
- src/ifo.rs — IFO parser (VIDEO_TS.IFO, VTS_XX_0.IFO, PGC chains, cells, streams) — 13 tests
- src/mux/ps.rs — MPEG-2 Program Stream demuxer (pack headers, PES, private stream 1) — 12 tests
- src/mux/codec/mpeg2.rs — MPEG-2 video parser (sequence headers, I-frame detection) — 15 tests
- src/css/crack.rs — split-attack algorithm (LFSR cipher needs verification — test ignored)

226 tests total (was 186), 1 ignored (CSS crack needs cipher verification).
This commit is contained in:
MattJackson
2026-04-11 16:52:22 +00:00
parent 6de4ee4b5c
commit 01235ff347
57 changed files with 6189 additions and 1519 deletions
+23 -10
View File
@@ -8,7 +8,7 @@
//! MMC-6 §5.3.10 — Feature 010Ch (Firmware Information)
use crate::error::Result;
use crate::scsi::{ScsiTransport, DataDirection};
use crate::scsi::{DataDirection, ScsiTransport};
/// Drive identity from standard SCSI commands.
///
@@ -64,7 +64,8 @@ impl DriveId {
let firmware_date = if result.bytes_transferred > 12 {
String::from_utf8_lossy(&gc[12..24.min(result.bytes_transferred)])
.trim().to_string()
.trim()
.to_string()
} else {
String::new()
};
@@ -72,12 +73,19 @@ impl DriveId {
// GET CONFIGURATION Feature 0108h — Serial Number
let mut gc_serial = vec![0u8; 256];
let cdb_serial = [0x46, 0x02, 0x01, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00];
let serial_number = if let Ok(r) = transport.execute(&cdb_serial, DataDirection::FromDevice, &mut gc_serial, 5000) {
let serial_number = if let Ok(r) =
transport.execute(&cdb_serial, DataDirection::FromDevice, &mut gc_serial, 5000)
{
if r.bytes_transferred > 12 {
String::from_utf8_lossy(&gc_serial[12..r.bytes_transferred])
.trim().to_string()
} else { String::new() }
} else { String::new() };
.trim()
.to_string()
} else {
String::new()
}
} else {
String::new()
};
Ok(DriveId {
vendor_id: ascii_field(&inquiry, 8, 16),
@@ -111,21 +119,26 @@ impl DriveId {
/// Used to look up this drive in the profile database.
/// All fields trimmed for consistent matching.
pub fn match_key(&self) -> String {
format!("{}|{}|{}|{}",
format!(
"{}|{}|{}|{}",
self.vendor_id.trim(),
self.product_id.trim(),
self.product_revision.trim(),
self.vendor_specific.trim())
self.vendor_specific.trim()
)
}
}
impl std::fmt::Display for DriveId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} {} {} {}",
write!(
f,
"{} {} {} {}",
self.vendor_id.trim(),
self.product_id.trim(),
self.product_revision.trim(),
self.vendor_specific.trim())
self.vendor_specific.trim()
)
}
}