Skip to content

Commit

Permalink
fix: correct merge code variables across PHI instructions (#930)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Nov 9, 2020
1 parent cd612b4 commit 0deafb7
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,27 @@ public List<PhiInsn> getUsedInPhi() {
return usedInPhi;
}

/**
* Concat assign PHI insn and usedInPhi
*/
public List<PhiInsn> getPhiList() {
InsnNode assignInsn = getAssign().getParentInsn();
if (assignInsn != null && assignInsn.getType() == InsnType.PHI) {
PhiInsn assignPhi = (PhiInsn) assignInsn;
if (usedInPhi == null) {
return Collections.singletonList(assignPhi);
}
List<PhiInsn> list = new ArrayList<>(1 + usedInPhi.size());
list.add(assignPhi);
list.addAll(usedInPhi);
return list;
}
if (usedInPhi == null) {
return Collections.emptyList();
}
return usedInPhi;
}

public boolean isUsedInPhi() {
return usedInPhi != null && !usedInPhi.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ public static void initCodeVar(SSAVar ssaVar) {
}

private static void setCodeVar(SSAVar ssaVar, CodeVar codeVar) {
List<PhiInsn> usedInPhiList = ssaVar.getUsedInPhi();
if (!usedInPhiList.isEmpty()) {
List<PhiInsn> phiList = ssaVar.getPhiList();
if (!phiList.isEmpty()) {
Set<SSAVar> vars = new LinkedHashSet<>();
vars.add(ssaVar);
collectConnectedVars(usedInPhiList, vars);
collectConnectedVars(phiList, vars);
setCodeVarType(codeVar, vars);
vars.forEach(var -> {
if (var.isCodeVarSet()) {
Expand Down Expand Up @@ -105,15 +105,18 @@ private static void setCodeVarType(CodeVar codeVar, Set<SSAVar> vars) {
}

private static void collectConnectedVars(List<PhiInsn> phiInsnList, Set<SSAVar> vars) {
if (phiInsnList.isEmpty()) {
return;
}
for (PhiInsn phiInsn : phiInsnList) {
SSAVar resultVar = phiInsn.getResult().getSVar();
if (vars.add(resultVar)) {
collectConnectedVars(resultVar.getUsedInPhi(), vars);
collectConnectedVars(resultVar.getPhiList(), vars);
}
phiInsn.getArguments().forEach(arg -> {
SSAVar sVar = ((RegisterArg) arg).getSVar();
if (vars.add(sVar)) {
collectConnectedVars(sVar.getUsedInPhi(), vars);
collectConnectedVars(sVar.getPhiList(), vars);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
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 TestVariablesInLoop extends SmaliTest {

@Test
public void test() {
assertThat(getClassNodeFromSmali())
.code()
.containsOne("int i;")
.countString(2, "i = 0;")
.doesNotContain("i3");
}
}
103 changes: 103 additions & 0 deletions jadx-core/src/test/smali/variables/TestVariablesInLoop.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
.class public abstract Lvariables/TestVariablesInLoop;
.super Ljava/lang/Object;
.source "SourceFile"

.implements Ljava/util/List;

.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/lang/Object;",
"Ljava/util/List<",
"Ljava/lang/Long;",
">;"
}
.end annotation

.method static test(Ljava/util/List;)I
.locals 5
.annotation system Ldalvik/annotation/Signature;
value = {
"(",
"Ljava/util/List<",
"Ljava/lang/Long;",
">;)I"
}
.end annotation

invoke-interface {p0}, Ljava/util/List;->size()I

move-result v0

const/4 v1, 0x0

if-nez v0, :cond_0

return v1

:cond_0
instance-of v2, p0, Lvariables/TestVariablesInLoop;

if-eqz v2, :cond_1

check-cast p0, Lvariables/TestVariablesInLoop;

const/4 v2, 0x0

:goto_0
if-ge v1, v0, :cond_2

invoke-virtual {p0, v1}, Lvariables/TestVariablesInLoop;->getLong(I)J

move-result-wide v3

invoke-static {v3, v4}, Lvariables/TestVariablesInLoop;->mth(J)I

move-result v3

add-int/2addr v2, v3

add-int/lit8 v1, v1, 0x1

goto :goto_0

:cond_1
const/4 v2, 0x0

:goto_1
if-ge v1, v0, :cond_2

invoke-interface {p0, v1}, Ljava/util/List;->get(I)Ljava/lang/Object;

move-result-object v3

check-cast v3, Ljava/lang/Long;

invoke-virtual {v3}, Ljava/lang/Long;->longValue()J

move-result-wide v3

invoke-static {v3, v4}, Lvariables/TestVariablesInLoop;->mth(J)I

move-result v3

add-int/2addr v2, v3

add-int/lit8 v1, v1, 0x1

goto :goto_1

:cond_2
return v2
.end method

.method public final getLong(I)J
.locals 2
const/16 v0, 0x0
return-wide v0
.end method

.method static mth(J)I
.locals 2
const/4 v0, 0x0
return v0
.end method

0 comments on commit 0deafb7

Please sign in to comment.