# HG changeset patch # User Emmanuel Gil Peyrot # Date 1566519848 -7200 # Node ID 3ff1af76e41385471d6462d2eb38c4f27aeaa635 # Parent 14fddc27e6f5865f8502937dbb16a9cc179133ee anm0: only use recoverable errors, no panics except for anm0 asserts. diff --git a/src/th06/anm0.rs b/src/th06/anm0.rs --- a/src/th06/anm0.rs +++ b/src/th06/anm0.rs @@ -89,8 +89,11 @@ fn parse_name(i: &[u8], is_present: bool return Ok((i, String::new())); } let (_, slice) = take_while_m_n(0, 32, |c| c != 0)(i)?; - // XXX: no unwrap! - let string = String::from_utf8(slice.to_vec()).unwrap(); + let string = match String::from_utf8(slice.to_vec()) { + Ok(string) => string, + // XXX: use a more specific error instead. + Err(_) => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof))) + }; Ok((i, string)) } @@ -120,8 +123,7 @@ macro_rules! declare_anm_instructions { ),* } - fn parse_instruction_args(input: &[u8], opcode: u8) -> IResult<&[u8], Instruction> { - let mut i = &input[..]; + fn parse_instruction_args(mut i: &[u8], opcode: u8) -> IResult<&[u8], Instruction> { let instr = match opcode { $( $opcode => { @@ -132,7 +134,8 @@ macro_rules! declare_anm_instructions { Instruction::$name($($arg),*) } )* - _ => unreachable!() + // XXX: use a more specific error instead. + _ => return Err(nom::Err::Failure((i, nom::error::ErrorKind::Eof))) }; Ok((i, instr)) } @@ -213,15 +216,24 @@ fn parse_anm0(input: &[u8]) -> IResult<& i = i2; } + if input.len() < start_offset + first_name_offset as usize { + return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); + } let i = &input[start_offset + first_name_offset as usize..]; let (_, first_name) = parse_name(i, first_name_offset > 0)?; + if input.len() < start_offset + second_name_offset as usize { + return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); + } let i = &input[start_offset + second_name_offset as usize..]; let (_, second_name) = parse_name(i, second_name_offset > 0)?; let mut sprites = vec![]; let mut i; for offset in sprite_offsets { + if input.len() < start_offset + offset { + return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); + } i = &input[start_offset + offset..]; let (_, sprite) = parse_sprite(i)?; sprites.push(sprite); @@ -229,6 +241,9 @@ fn parse_anm0(input: &[u8]) -> IResult<& let mut scripts = HashMap::new(); for (index, offset) in script_offsets { + if input.len() < start_offset + offset { + return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); + } i = &input[start_offset + offset..]; let mut instruction_offsets = vec![]; @@ -255,8 +270,11 @@ fn parse_anm0(input: &[u8]) -> IResult<& let result = instruction_offsets.binary_search(&(*offset as usize)); match result { Ok(ptr) => *offset = ptr as u32, - // TODO: make that a recoverable error instead. - Err(ptr) => panic!("Instruction offset not found for pointer: {}", ptr), + Err(ptr) => { + // XXX: use a more specific error instead. + return Err(nom::Err::Failure((input, nom::error::ErrorKind::Eof))); + //println!("Instruction offset not found for pointer: {}", ptr); + } } } Instruction::InterruptLabel(interrupt) => {