From 7d689a85eac7279741be22a0297dffb73db043e1 Mon Sep 17 00:00:00 2001 From: Skylot <118523+skylot@users.noreply.github.com> Date: Thu, 2 Apr 2026 22:29:30 +0100 Subject: [PATCH] fix: remove result in wrapped insntructions (#2835) --- .../core/dex/instructions/args/InsnArg.java | 7 +- .../dex/instructions/args/InsnWrapArg.java | 9 +- .../core/dex/visitors/SimplifyVisitor.java | 3 +- .../visitors/shrink/CodeShrinkVisitor.java | 3 +- .../java/jadx/core/utils/DebugChecks.java | 3 + .../java/jadx/core/utils/InsnRemover.java | 2 +- .../integration/variables/TestVariables8.java | 17 ++++ .../test/smali/variables/TestVariables8.smali | 86 +++++++++++++++++++ 8 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/variables/TestVariables8.java create mode 100644 jadx-core/src/test/smali/variables/TestVariables8.smali diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index a678a40fa..4742dfd6e 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -131,6 +131,7 @@ public abstract class InsnArg extends Typed { } } } + RegisterArg resArg = insn.getResult(); InsnArg arg = wrapInsnIntoArg(insn); InsnArg oldArg = parent.getArg(i); if (arg.getType() == ArgType.UNKNOWN) { @@ -141,6 +142,8 @@ public abstract class InsnArg extends Typed { InsnRemover.unbindArgUsage(mth, oldArg); if (unbind) { InsnRemover.unbindArgUsage(mth, this); + } + if (resArg != null && !insn.contains(AFlag.FORCE_ASSIGN_INLINE)) { // result not needed in wrapped insn InsnRemover.unbindResult(mth, insn); insn.setResult(null); @@ -323,9 +326,7 @@ public abstract class InsnArg extends Typed { return copy; } - public InsnArg duplicate() { - return this; - } + public abstract InsnArg duplicate(); public String toShortString() { return this.toString(); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java index d463c9a4d..8f3076eca 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java @@ -41,7 +41,14 @@ public final class InsnWrapArg extends InsnArg { @Override public InsnArg duplicate() { - InsnWrapArg copy = new InsnWrapArg(wrappedInsn.copyWithoutResult()); + InsnNode wrapInsn = wrappedInsn; + InsnNode wrapInsnCopy = wrapInsn.copyWithoutResult(); + if (wrapInsn.getResult() != null && wrapInsn.contains(AFlag.FORCE_ASSIGN_INLINE)) { + // keep same SSA var in result arg, this will break previous version, mark it for removal + wrapInsnCopy.setResult(wrapInsn.getResult().duplicate()); + wrapInsn.add(AFlag.DONT_GENERATE); + } + InsnWrapArg copy = new InsnWrapArg(wrapInsnCopy); copy.setType(type); return copyCommonParams(copy); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java index 176f6b592..d40a59430 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java @@ -114,8 +114,7 @@ public class SimplifyVisitor extends AbstractVisitor { InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); InsnNode replaceInsn = simplifyInsn(mth, wrapInsn, insn); if (replaceInsn != null) { - arg.wrapInstruction(mth, replaceInsn, false); - InsnRemover.unbindInsn(mth, wrapInsn); + arg.wrapInstruction(mth, replaceInsn); changed = true; } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java index ac503b990..048bce202 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java @@ -200,8 +200,7 @@ public class CodeShrinkVisitor extends AbstractVisitor { if (!InsnRemover.removeWithoutUnbind(mth, assignBlock, assignInsn)) { return false; } - InsnArg replaceArg = InsnArg.wrapInsnIntoArg(assignInsn); - useInsn.replaceArg(useArg, replaceArg); + useArg.wrapInstruction(mth, assignInsn); return true; } diff --git a/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java b/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java index b5f98be3e..0717efd1a 100644 --- a/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java +++ b/jadx-core/src/main/java/jadx/core/utils/DebugChecks.java @@ -85,6 +85,9 @@ public class DebugChecks { && !mth.contains(AFlag.DONT_GENERATE)) { throw new JadxRuntimeException("Not generated wrapped insn: \n " + wrapInsn + ",\nouter insn:\n " + insn); } + if (wrapInsn.getResult() != null && !wrapInsn.contains(AFlag.FORCE_ASSIGN_INLINE)) { + throw new JadxRuntimeException("Wrapped insn result should be removed: \n " + wrapInsn + ",\nouter insn:\n " + insn); + } checkInsn(mth, block, wrapInsn); } } diff --git a/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java b/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java index 3b93d9f79..321141967 100644 --- a/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java +++ b/jadx-core/src/main/java/jadx/core/utils/InsnRemover.java @@ -151,7 +151,7 @@ public class InsnRemover { } // check if all usage only in not generated instructions if (allMatch(ssaVar.getUseList(), - arg -> arg.contains(AFlag.DONT_GENERATE) || (InsnUtils.contains(arg.getParentInsn(), AFlag.DONT_GENERATE)))) { + arg -> arg.contains(AFlag.DONT_GENERATE) || InsnUtils.contains(arg.getParentInsn(), AFlag.DONT_GENERATE))) { for (RegisterArg arg : ssaVar.getUseList()) { arg.resetSSAVar(); } diff --git a/jadx-core/src/test/java/jadx/tests/integration/variables/TestVariables8.java b/jadx-core/src/test/java/jadx/tests/integration/variables/TestVariables8.java new file mode 100644 index 000000000..7a23c6ecf --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/variables/TestVariables8.java @@ -0,0 +1,17 @@ +package jadx.tests.integration.variables; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.SmaliTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestVariables8 extends SmaliTest { + @Test + public void testNoDebug() { + getArgs().setDebugInfo(false); + assertThat(getClassNodeFromSmali()) + .code() + .doesNotContain("r0"); + } +} diff --git a/jadx-core/src/test/smali/variables/TestVariables8.smali b/jadx-core/src/test/smali/variables/TestVariables8.smali new file mode 100644 index 000000000..1d3968bd7 --- /dev/null +++ b/jadx-core/src/test/smali/variables/TestVariables8.smali @@ -0,0 +1,86 @@ +.class Lvariables/TestVariables8; +.super Ljava/lang/Object; + +.method private static test(III)J + .registers 13 + .param p0, "k" # I + .param p1, "j" # I + .param p2, "i" # I + + .prologue + const-wide/16 v4, -0x1 + const/4 v8, 0x1 + + .line 614 + shl-int/lit8 v6, p0, 0x6 + xor-int/lit8 v7, p1, -0x1 + and-int/lit8 v7, v7, 0x3f + or-int v0, v6, v7 + + .local v0, "e":I + const/4 v1, 0x6 + + .line 616 + .local v1, "l":I + :goto_c + if-ltz v1, :cond_13 + + shl-int v6, v8, v1 + and-int/2addr v6, v0 + + if-eqz v6, :cond_16 + + .line 619 + :cond_13 + if-ge v1, v8, :cond_19 + + .line 633 + :cond_15 + return-wide v4 + + .line 617 + :cond_16 + add-int/lit8 v1, v1, -0x1 + goto :goto_c + + .line 620 + :cond_19 + shl-int v0, v8, v1 + .line 621 + add-int/lit8 v1, v0, -0x1 + .line 622 + and-int/2addr p1, v1 + .line 623 + if-eq p1, v1, :cond_15 + + .line 624 + and-int/2addr p2, v1 + .line 625 + add-int/lit8 v6, p1, 0x1 + rsub-int/lit8 v6, v6, 0x40 + ushr-long v2, v4, v6 + + .line 626 + .local v2, "m":J + ushr-long v6, v2, p2 + sub-int v8, v0, p2 + shl-long v8, v2, v8 + or-long v2, v6, v8 + + .line 627 + move-wide v4, v2 + .line 628 + .local v4, "r":J + move p2, v0 + .line 629 + :goto_31 + const/16 v6, 0x40 + if-ge p2, v6, :cond_15 + + .line 630 + shl-long v6, v2, p2 + or-long/2addr v4, v6 + .line 631 + add-int/2addr p2, v0 + goto :goto_31 +.end method