diff --git a/src/scene/model/underlay_vector/dgn8.rs b/src/scene/model/underlay_vector/dgn8.rs index 4bc4d8605..08e52fc7e 100644 --- a/src/scene/model/underlay_vector/dgn8.rs +++ b/src/scene/model/underlay_vector/dgn8.rs @@ -39,16 +39,24 @@ fn u32_at(b: &[u8], at: usize) -> Option { impl<'a> Cfb<'a> { fn open(b: &'a [u8]) -> Option { - if !b.starts_with(&[0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]) { + // The 512-byte header, with the only two sector sizes the format + // has (512 and 4096 bytes); anything else is not a compound file. + if b.len() < 512 || !b.starts_with(&[0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1]) { return None; } - let sector = 1usize << u16::from_le_bytes([b[30], b[31]]); + let sector_shift = u16::from_le_bytes([b[30], b[31]]); + if sector_shift != 9 && sector_shift != 12 { + return None; + } + let sector = 1usize << sector_shift; let mini_sector_shift = u16::from_le_bytes([b[32], b[33]]); if mini_sector_shift != 6 { return None; } let mut difat: Vec = (0..109).filter_map(|i| u32_at(b, 76 + i * 4)).filter(|&v| v < END).collect(); - let (mut next, mut count) = (u32_at(b, 68)?, u32_at(b, 72)?); + // The DIFAT chain cannot hold more sectors than the file does, so a + // looping chain stops there. + let (mut next, mut count) = (u32_at(b, 68)?, u32_at(b, 72)?.min((b.len() / sector) as u32)); while count > 0 && next < END { let at = (next as usize + 1) * sector; for i in 0..sector / 4 - 1 { diff --git a/src/scene/model/underlay_vector/dwf.rs b/src/scene/model/underlay_vector/dwf.rs index 094f9b19a..25f2b1dff 100644 --- a/src/scene/model/underlay_vector/dwf.rs +++ b/src/scene/model/underlay_vector/dwf.rs @@ -270,7 +270,9 @@ mod w2d { _ => {} } } - let body = &self.b[start + 1..self.i.saturating_sub(1)]; + // A stream cut off right after its '(' has no body at all. + let end = self.i.saturating_sub(1).max(start + 1); + let body = self.b.get(start + 1..end)?; let name_len = body.iter().position(|c| c.is_ascii_whitespace() || *c == b'(').unwrap_or(body.len()); Some((String::from_utf8_lossy(&body[..name_len]).to_string(), &body[name_len..])) }