From 13f1267eacd43250d40342d95e2901c347b09fdf Mon Sep 17 00:00:00 2001 From: LagoLunatic Date: Sun, 3 May 2026 21:27:12 -0400 Subject: [PATCH] Fix several issues with string literal detection (#351) * Support detecting more symbol names for strings * Fix string detectiong being broken for encodings that use null terminators * Add test cases for string detection and decoding * Fix test helper function sometimes being considered dead code * Clippy fixes --- objdiff-core/src/arch/mod.rs | 39 ++++---- objdiff-core/src/arch/ppc/flow_analysis.rs | 2 + objdiff-core/src/arch/ppc/mod.rs | 7 +- objdiff-core/tests/arch_ppc.rs | 87 ++++++++++++++++++ objdiff-core/tests/common.rs | 22 +++++ .../tests/data/ppc/KinectSharePanel.obj | Bin 0 -> 47532 bytes objdiff-wasm/src/api.rs | 4 +- 7 files changed, 139 insertions(+), 22 deletions(-) create mode 100644 objdiff-core/tests/data/ppc/KinectSharePanel.obj diff --git a/objdiff-core/src/arch/mod.rs b/objdiff-core/src/arch/mod.rs index 59da3cc..5d44aae 100644 --- a/objdiff-core/src/arch/mod.rs +++ b/objdiff-core/src/arch/mod.rs @@ -42,15 +42,15 @@ pub mod x86; pub const OPCODE_INVALID: u16 = u16::MAX; pub const OPCODE_DATA: u16 = u16::MAX - 1; -const SUPPORTED_ENCODINGS: [(&encoding_rs::Encoding, &str); 7] = [ +const SUPPORTED_ENCODINGS_WITH_NULL_TERM: [(&encoding_rs::Encoding, &str); 5] = [ (encoding_rs::UTF_8, "UTF-8"), (encoding_rs::SHIFT_JIS, "Shift JIS"), - (encoding_rs::UTF_16BE, "UTF-16BE"), - (encoding_rs::UTF_16LE, "UTF-16LE"), (encoding_rs::WINDOWS_1252, "Windows-1252"), (encoding_rs::EUC_JP, "EUC-JP"), (encoding_rs::BIG5, "Big5"), ]; +const SUPPORTED_ENCODINGS_NO_NULL_TERM: [(&encoding_rs::Encoding, &str); 2] = + [(encoding_rs::UTF_16BE, "UTF-16BE"), (encoding_rs::UTF_16LE, "UTF-16LE")]; /// Represents the type of data associated with an instruction #[derive(PartialEq)] @@ -174,24 +174,27 @@ impl DataType { strs.push((format!("{bytes:#?}"), None, None)); } DataType::String => { - // Special case to display (ASCII) as the label for ASCII-only strings. - let mut is_ascii = false; - if bytes.is_ascii() - && let Ok(str) = str::from_utf8(bytes) - { - let trimmed = str.trim_end_matches('\0'); - if !trimmed.is_empty() { - let copy_string = escape_special_ascii_characters(trimmed); - strs.push((trimmed.to_string(), Some("ASCII".into()), Some(copy_string))); - is_ascii = true; + if let Some(nul_idx) = bytes.iter().position(|&c| c == b'\0') { + let str_bytes = &bytes[..nul_idx]; + // Special case to display (ASCII) as the label for ASCII-only strings. + let (cow, _, had_errors) = encoding_rs::UTF_8.decode(str_bytes); + if !had_errors && cow.is_ascii() { + let string = format!("{cow}"); + let copy_string = escape_special_ascii_characters(&string); + strs.push((string, Some("ASCII".into()), Some(copy_string))); + } + for (encoding, encoding_name) in SUPPORTED_ENCODINGS_WITH_NULL_TERM { + let (cow, _, had_errors) = encoding.decode(str_bytes); + // Avoid showing ASCII-only strings more than once if the encoding is ASCII-compatible. + if !had_errors && (!encoding.is_ascii_compatible() || !cow.is_ascii()) { + let string = format!("{cow}"); + let copy_string = escape_special_ascii_characters(&string); + strs.push((string, Some(encoding_name.into()), Some(copy_string))); + } } } - for (encoding, encoding_name) in SUPPORTED_ENCODINGS { - // Avoid showing ASCII-only strings more than once if the encoding is ASCII-compatible. - if is_ascii && encoding.is_ascii_compatible() { - continue; - } + for (encoding, encoding_name) in SUPPORTED_ENCODINGS_NO_NULL_TERM { let (cow, _, had_errors) = encoding.decode(bytes); if had_errors { continue; diff --git a/objdiff-core/src/arch/ppc/flow_analysis.rs b/objdiff-core/src/arch/ppc/flow_analysis.rs index 13f7273..44b620f 100644 --- a/objdiff-core/src/arch/ppc/flow_analysis.rs +++ b/objdiff-core/src/arch/ppc/flow_analysis.rs @@ -513,6 +513,8 @@ pub fn ppc_data_flow_analysis( ) } +// Note: This function only supports MWCC ASCII strings. +// Other encodings and other compilers are currently not supported. fn get_string_data(obj: &Object, symbol_index: usize, offset: Simm) -> Option<&str> { if let Some(sym) = obj.symbols.get(symbol_index) && sym.name.starts_with("@stringBase") diff --git a/objdiff-core/src/arch/ppc/mod.rs b/objdiff-core/src/arch/ppc/mod.rs index b8a6bab..0cefda2 100644 --- a/objdiff-core/src/arch/ppc/mod.rs +++ b/objdiff-core/src/arch/ppc/mod.rs @@ -359,9 +359,12 @@ impl Arch for ArchPpc { fn guess_data_type(&self, resolved: ResolvedInstructionRef, bytes: &[u8]) -> Option { if resolved.relocation.is_some_and(|r| { - r.symbol.name.starts_with("@stringBase") || r.symbol.name.starts_with("$SG") + r.symbol.name.starts_with("@stringBase") + || r.symbol.name.starts_with("@wstringBase") + || r.symbol.name.starts_with("$SG") + || r.symbol.demangled_name == Some("`string'".to_string()) }) { - // Pooled string. + // Compiler-generated symbol name for a string or a pool of strings. return Some(DataType::String); } let opcode = powerpc::Opcode::from(resolved.ins_ref.opcode); diff --git a/objdiff-core/tests/arch_ppc.rs b/objdiff-core/tests/arch_ppc.rs index 78aaaea..57ae05e 100644 --- a/objdiff-core/tests/arch_ppc.rs +++ b/objdiff-core/tests/arch_ppc.rs @@ -122,3 +122,90 @@ fn read_vmx128_coff() { let output = common::display_diff(&obj, &diff, symbol_idx, &diff_config); insta::assert_snapshot!(output); } + +#[test] +#[cfg(feature = "ppc")] +fn decode_sjis_pooled_strings() { + // Test multiple pooled Shift JIS strings separated by a single null byte between entries. (MWCC) + let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() }; + let obj = obj::read::parse( + include_object!("data/ppc/m_Do_hostIO.o"), + &diff_config, + diff::DiffSide::Base, + ) + .unwrap(); + common::assert_literal_value( + &obj, + &diff_config, + "createChild__16mDoHIO_subRoot_cFPCcP13JORReflexible", + 15, + "Shift JIS", + "危険:既に登録されているホストIOをふたたび登録しようとしています<%s>\n", + ); + common::assert_literal_value( + &obj, + &diff_config, + "createChild__16mDoHIO_subRoot_cFPCcP13JORReflexible", + 42, + "Shift JIS", + "ホストIOの空きエントリがありません。登録できませんでした。\n", + ); +} + +#[test] +#[cfg(feature = "ppc")] +fn decode_utf16_unpooled_strings() { + // Test unpooled UTF-16BE wide strings with null bytes at the start, end, and in the middle of the string. (MSVC) + let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() }; + let obj = obj::read::parse( + include_object!("data/ppc/KinectSharePanel.obj"), + &diff_config, + diff::DiffSide::Base, + ) + .unwrap(); + common::assert_literal_value( + &obj, + &diff_config, + "?OnPostLink@KinectSharePanel@@AAA?AVDataNode@@PAVDataArray@@@Z", + 84, + "UTF-16BE", + "Title Text", + ); + common::assert_literal_value( + &obj, + &diff_config, + "?OnPostLink@KinectSharePanel@@AAA?AVDataNode@@PAVDataArray@@@Z", + 120, + "UTF-16BE", + "http://www.dancecentral.com/content-assets/2012/06/2012E3LogoBox_tn.jpg", + ); +} + +#[test] +#[cfg(feature = "ppc")] +fn decode_ascii_strings_with_null_padding() { + // Test unpooled ASCII strings with more than one null byte at the end. + let diff_config = diff::DiffObjConfig { combine_data_sections: true, ..Default::default() }; + let obj = obj::read::parse( + include_object!("data/ppc/vmx128.obj"), + &diff_config, + diff::DiffSide::Base, + ) + .unwrap(); + common::assert_literal_value( + &obj, + &diff_config, + "?PrintVector@@YAXPBDU__vector4@@@Z", + 24, + "ASCII", + "%s: [%.2f, %.2f, %.2f, %.2f]\n", + ); + common::assert_literal_value( + &obj, + &diff_config, + "?ReservedRegisterExample@@YAXXZ", + 59, + "ASCII", + "Result from vr66", + ); +} diff --git a/objdiff-core/tests/common.rs b/objdiff-core/tests/common.rs index 311c622..330a5da 100644 --- a/objdiff-core/tests/common.rs +++ b/objdiff-core/tests/common.rs @@ -50,3 +50,25 @@ macro_rules! include_object { include_bytes_align_as!(u64, $path) }; } + +#[allow(dead_code)] +pub fn assert_literal_value( + obj: &Object, + diff_config: &DiffObjConfig, + function_name: &str, + ins_row_idx: usize, + literal_label: &str, + literal_value: &str, +) { + let symbol_idx = obj.symbols.iter().position(|s| s.name == function_name).unwrap(); + let diff = objdiff_core::diff::code::no_diff_code(obj, symbol_idx, diff_config).unwrap(); + let ins_ref = diff.instruction_rows[ins_row_idx].ins_ref.unwrap(); + let resolved = obj.resolve_instruction_ref(symbol_idx, ins_ref).unwrap(); + let literals = objdiff_core::diff::display::display_ins_data_literals(obj, resolved); + let target_literal = literals + .iter() + .find(|(_, label_override, _)| *label_override == Some(literal_label.to_string())); + assert_ne!(target_literal, None); + let (literal, _, _) = target_literal.unwrap(); + assert_eq!(literal, literal_value); +} diff --git a/objdiff-core/tests/data/ppc/KinectSharePanel.obj b/objdiff-core/tests/data/ppc/KinectSharePanel.obj new file mode 100644 index 0000000000000000000000000000000000000000..b8571db7b88ce9b657bec57efcbd658868c2c302 GIT binary patch literal 47532 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 literal 0 HcmV?d00001 diff --git a/objdiff-wasm/src/api.rs b/objdiff-wasm/src/api.rs index 980273c..ed1c686 100644 --- a/objdiff-wasm/src/api.rs +++ b/objdiff-wasm/src/api.rs @@ -225,7 +225,7 @@ impl GuestDisplay for Component { let obj_diff = diff.get::(); let obj = obj_diff.0.as_ref(); let symbol_display = from_symbol_ref(symbol_ref); - diff::display::symbol_context(obj, symbol_display.symbol as usize) + diff::display::symbol_context(obj, symbol_display.symbol) .into_iter() .map(ContextItem::from) .collect() @@ -237,7 +237,7 @@ impl GuestDisplay for Component { let addend = 0; // TODO let override_color = None; // TODO: colorize replaced/deleted/inserted relocations let symbol_display = from_symbol_ref(symbol_ref); - diff::display::symbol_hover(obj, symbol_display.symbol as usize, addend, override_color) + diff::display::symbol_hover(obj, symbol_display.symbol, addend, override_color) .into_iter() .map(HoverItem::from) .collect()