From be5922a726dfa46e0a42530347b691e2a7877c47 Mon Sep 17 00:00:00 2001 From: Jean-Marie 'Histausse' Mineau Date: Mon, 3 Mar 2025 15:03:39 +0100 Subject: [PATCH] allow multiple label at the same address when parsing .dex --- androscalpel/src/apk.rs | 178 ++++++++-------------------------------- 1 file changed, 36 insertions(+), 142 deletions(-) diff --git a/androscalpel/src/apk.rs b/androscalpel/src/apk.rs index cb8670b..111ebe5 100644 --- a/androscalpel/src/apk.rs +++ b/androscalpel/src/apk.rs @@ -852,19 +852,20 @@ impl Apk { } /// Convert an instruction format to an instruction. + #[allow(clippy::type_complexity)] fn instruction_format_to_instruction( format: &InsFormat, addr: usize, insns_ref: &HashMap, dex: &DexFileReader, label_ins: &mut F, - ) -> Result)>> + ) -> Result>)>> where F: FnMut(&instructions::Instruction, usize) -> Option, { use crate::instructions::*; use InsFormat::*; - let mut labels = HashMap::new(); + let mut labels = HashMap::<_, Vec<_>>::new(); let ins = match format.clone() { Format10X { op: 0x00 } => Instruction::Nop {}, Format12X { op: 0x01, va, vb } => Instruction::Move { @@ -1037,12 +1038,7 @@ impl Apk { addr - (-(a as i64) as usize) }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::Goto { label } } Format20T { op: 0x29, a } => { @@ -1055,12 +1051,7 @@ impl Apk { addr - (-(a as i64) as usize) }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::Goto { label } } Format30T { op: 0x2a, a } => { @@ -1073,12 +1064,7 @@ impl Apk { addr - (-(a as i64) as usize) }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::Goto { label } } Format31T { op: 0x2b, va, b } => { @@ -1110,15 +1096,7 @@ impl Apk { addr - (-(target as i64) as usize) }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!( - "There is already a label at 0x{dest_addr:08X} with \ - an invalid name" - ); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); branches.insert(key, label); key += 1; } @@ -1164,15 +1142,7 @@ impl Apk { addr - (-target as usize) }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!( - "There is already a label at 0x{dest_addr:08X} with \ - an invalid name" - ); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); branches.insert(key, label); } Instruction::Switch { reg: va, branches } @@ -1257,12 +1227,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfEq { a: va, b: vb, @@ -1287,12 +1252,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfNe { a: va, b: vb, @@ -1317,12 +1277,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfLt { a: va, b: vb, @@ -1347,12 +1302,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfGe { a: va, b: vb, @@ -1377,12 +1327,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfGt { a: va, b: vb, @@ -1407,12 +1352,7 @@ impl Apk { addr - (-(c as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfLe { a: va, b: vb, @@ -1432,12 +1372,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfEqZ { a: va, label } } Format21T { op: 0x39, va, b } => { @@ -1453,12 +1388,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfNeZ { a: va, label } } Format21T { op: 0x3a, va, b } => { @@ -1474,12 +1404,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfLtZ { a: va, label } } Format21T { op: 0x3b, va, b } => { @@ -1495,12 +1420,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfGeZ { a: va, label } } Format21T { op: 0x3c, va, b } => { @@ -1516,12 +1436,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfGtZ { a: va, label } } Format21T { op: 0x3d, va, b } => { @@ -1537,12 +1452,7 @@ impl Apk { addr - (-(b as i64)) as usize }; let label = format!("label_{dest_addr:08X}"); - if let Some(old_label) = labels.insert(dest_addr, label.clone()) { - if old_label != label { - // TODO: internal error, panic? - bail!("There is already a label at 0x{dest_addr:08X} with an invalid name"); - } - } + labels.entry(dest_addr).or_default().push(label.clone()); Instruction::IfLeZ { a: va, label } } Format23X { @@ -2666,7 +2576,7 @@ impl Apk { .with_context(|| anyhow!("Invalid instruction {ins:?} found at {addr}: {format:?}"))?; if let Some(label) = label_ins(&ins, addr) { //let label = format!("label_{addr:08X}"); - labels.insert(addr, label); + labels.entry(addr).or_default().push(label); } Ok(Some((ins, labels))) @@ -2705,7 +2615,7 @@ impl Apk { } else { (DebugInfo::EndOfData, None) }; - let mut labels: HashMap = HashMap::new(); + let mut labels: HashMap> = HashMap::new(); let mut tries = HashMap::new(); for TryItem { start_addr, @@ -2725,12 +2635,7 @@ impl Apk { .get_handler_at_offset(handler_off)?; let default_handler = if let Some(Uleb128(addr)) = *catch_all_addr { let label = format!("label_{addr:08X}"); - if let Some(label_) = labels.insert(addr as usize, label.clone()) { - if label_ != label { - // TODO: that's an internal error - bail!("Label collision at 0x{addr:08X}: {label_} and {label}"); - } - } + labels.entry(addr as usize).or_default().push(label.clone()); Some(label) } else { None @@ -2742,22 +2647,15 @@ impl Apk { } in handlers.iter().cloned() { let label = format!("label_{addr:08X}"); - if let Some(label_) = labels.insert(addr as usize, label.clone()) { - if label_ != label { - // TODO: that's an internal error - bail!("Label collision at 0x{addr:08X}: {label_} and {label}"); - } - } + labels.entry(addr as usize).or_default().push(label.clone()); handlers_.push((Self::get_id_type_from_idx(type_idx as usize, dex)?, label)) } let dest_addr = start_addr + insn_count as u32; let end_label = format!("label_{dest_addr:08X}"); - if let Some(label_) = labels.insert(dest_addr as usize, end_label.clone()) { - if label_ != end_label { - // TODO: that's an internal error - bail!("Label collision at 0x{dest_addr:08X}: {label_} and {end_label}"); - } - } + labels + .entry(dest_addr as usize) + .or_default() + .push(end_label.clone()); let try_ = Instruction::Try { end_label, handlers: handlers_, @@ -2789,14 +2687,6 @@ impl Apk { )? { instructions.push((addr, ins)); addr += ins_f.size() / 2; - for (key, val) in &ins_labels { - if let Some(val_) = ins_labels.get(key) { - if val_ != val { - // TODO: internal error, panic? - bail!("Label collision at 0x{key:08X}: {val_} and {val}"); - } - } - } labels.extend(ins_labels); } } @@ -2852,8 +2742,10 @@ impl Apk { if let Some(try_) = tries.remove(&addr) { insns.push(try_); } - if let Some(label) = labels.remove(&addr) { - insns.push(Instruction::Label { name: label }); + if let Some(label_l) = labels.remove(&addr) { + for label in label_l.into_iter() { + insns.push(Instruction::Label { name: label }); + } } insns.push(ins); } @@ -2862,8 +2754,10 @@ impl Apk { if let Some(try_) = tries.remove(&addr) { insns.push(try_); } - if let Some(label) = labels.remove(&addr) { - insns.push(Instruction::Label { name: label }); + if let Some(label_l) = labels.remove(&addr) { + for label in label_l.into_iter() { + insns.push(Instruction::Label { name: label }); + } } if !labels.is_empty() { bail!("Could not put all label as instructions (label out of insns?)");