fix: remove result in wrapped insntructions (#2835)

This commit is contained in:
Skylot
2026-04-02 22:29:30 +01:00
parent c7a162d827
commit 7d689a85ea
8 changed files with 121 additions and 9 deletions
@@ -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();
@@ -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);
}
@@ -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;
}
}
@@ -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;
}
@@ -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);
}
}
@@ -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();
}
@@ -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");
}
}
@@ -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