diff --git a/src/id0/root_info.rs b/src/id0/root_info.rs index 99a2623..f709642 100644 --- a/src/id0/root_info.rs +++ b/src/id0/root_info.rs @@ -275,7 +275,10 @@ impl RootInfo { match version { // TODO old version may contain extra data at the end with unknown purpose ..=699 => {} - 700.. => ensure!(input.is_empty(), "Data left after the IDBParam",), + 700.. => { + #[cfg(feature = "restrictive")] + ensure!(input.is_empty(), "Data left after the IDBParam"); + } } Ok(param) } diff --git a/src/til.rs b/src/til.rs index 4ba5e05..ed163b4 100644 --- a/src/til.rs +++ b/src/til.rs @@ -392,9 +392,10 @@ impl Basic { // InnerRef fb47f2c2-3c08-4d40-b7ab-3c7736dce31d 0x480874 BT_UNK => { let bytes = match btmt { - BTMT_SIZE0 => { - return Err(anyhow!("forbidden use of BT_UNK")) - } + // A bare `BT_UNK` (type byte 0x00) is IDA's unknown type of unspecified + // size; treat it like `BT_UNKNOWN` rather than rejecting it, since it shows + // up in real databases (e.g. as a function argument/return type). + BTMT_SIZE0 => 0, BTMT_SIZE12 => 2, // BT_UNK_WORD BTMT_SIZE48 => 8, // BT_UNK_QWORD BTMT_SIZE128 => 0, // BT_UNKNOWN diff --git a/src/tools/dump_dirtree_funcs.rs b/src/tools/dump_dirtree_funcs.rs index 0fcf7ce..943cd62 100644 --- a/src/tools/dump_dirtree_funcs.rs +++ b/src/tools/dump_dirtree_funcs.rs @@ -20,13 +20,13 @@ fn dump_inner((id0, id1, id2): Id0Id1Id2Variant) -> Result<()> { if let Some(dirtree) = id0.dirtree_function_address()? { print_dirtree( |entry| { - print_function( - &id0, - &id1, - id2.as_ref(), - Address::from_raw(*entry), - ) - .unwrap() + let address = Address::from_raw(*entry); + if let Err(err) = + print_function(&id0, &id1, id2.as_ref(), address) + { + // Don't let a single unparsable function abort the whole dump. + println!("{:#x}: ", address.into_raw()); + } }, &dirtree, ); @@ -45,14 +45,12 @@ pub fn print_function( let root_info = id0.ida_info(root_info_idx)?; let image_base = root_info.netdelta(); let info = AddressInfo::new(id0, id1, id2, image_base, address); - let name = info - .as_ref() - .and_then(|info| info.label().transpose()) - .transpose()?; + // Tolerate per-function label/type parse failures so one bad entry doesn't abort the dump; + // such a function simply prints without the failing piece. + let name = info.as_ref().and_then(|info| info.label().ok().flatten()); let ty = info .as_ref() - .and_then(|info| info.tinfo(&root_info).transpose()) - .transpose()?; + .and_then(|info| info.tinfo(&root_info).ok().flatten()); print!("{:#x}:", address.into_raw()); match (name, ty) {