-
Notifications
You must be signed in to change notification settings - Fork 57
Description
Summary
When using objdiff-wasm, parsing the same .o file first as 'base' (for a one-sided diff) and then as 'target' (for a two-sided diff) causes the second comparison to return incorrect results.
Specifically, it reports a perfect match (0 differences) when there are actually significant differences between the two files.
Versions
objdiff-wasm: 3.6.1- Node.js: v22
Reproduction
The fixtures are MIPS big-endian ELF .o files.
The target.o has dual OBJECT+FUNC symbols for the same address.
git clone git@github.com:macabeus/objdiff-issue.git
cd objdiff-issue
npm install
# Correct behavior — reports differences:
node reproduce.mjs
# Bug — reports perfect match:
node reproduce.mjs --preparseWithout pre-parse (correct):
Skipping pre-parse step.
Comparing current.o (base) vs target.o (target)...
Matching: 22
Different: 20
✓ Differences correctly detected.
With pre-parse (bug):
Pre-parsing target.o as "base" (one-sided diff)...
Done.
Comparing current.o (base) vs target.o (target)...
Matching: 40
Different: 0
⚠ No differences reported — but the .o files contain different code!
What the repro script does
-
Without
--preparse: Parsescurrent.oas'base'andtarget.oas'target', runs a two-sided diff, and counts matching vs. differing instruction rows for symbolfunc_800B3F64_1E1014. Correctly reports 22 matching / 20 different. -
With
--preparse: First parsestarget.oas'base'and runs a one-sided diff (i.e.,runDiff(base, undefined, ...)). Then does the same two-sided comparison as above. This time it incorrectly reports 40 matching / 0 different.
The only difference between the two runs is the extra Object.parse() + runDiff() call on target.o before the real comparison. This suggests that WASM module state from the first parse leaks into the second.
Context
I discovered this while working on Mizuchi, a plugin-based pipeline runner.
One plugin was parsing the target .o to extract assembly (one-sided diff as 'base'), and later another plugin ran the actual two-sided comparison. The prior parse caused the comparison to always report a perfect match, masking real code differences.
I noticed later that it happens on Kappa too, when using the command Compare a symbol from two object files. It runs the pre-parsing to list the symbols before the actual diff.