fix: use correct approach to get prev block on path (#2239)
This commit is contained in:
@@ -115,8 +115,8 @@ public class ConstructorVisitor extends AbstractVisitor {
|
||||
|
||||
PhiInsn phiInsn = SSATransform.addPhi(mth, crossBlock, useArg.getRegNum());
|
||||
phiInsn.setResult(useArg.duplicate());
|
||||
phiInsn.bindArg(newResArg.duplicate(), BlockUtils.getPrevBlockOnPath(crossBlock, curBlock));
|
||||
phiInsn.bindArg(otherResArg.duplicate(), BlockUtils.getPrevBlockOnPath(crossBlock, otherBlock));
|
||||
phiInsn.bindArg(newResArg.duplicate(), BlockUtils.getPrevBlockOnPath(mth, crossBlock, curBlock));
|
||||
phiInsn.bindArg(otherResArg.duplicate(), BlockUtils.getPrevBlockOnPath(mth, crossBlock, otherBlock));
|
||||
phiInsn.rebindArgs();
|
||||
|
||||
otherCtr.setResult(otherResArg.duplicate());
|
||||
|
||||
@@ -37,6 +37,7 @@ import jadx.core.dex.regions.conditions.IfCondition;
|
||||
import jadx.core.dex.trycatch.CatchAttr;
|
||||
import jadx.core.dex.trycatch.ExceptionHandler;
|
||||
import jadx.core.utils.blocks.BlockSet;
|
||||
import jadx.core.utils.blocks.DFSIteration;
|
||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||
|
||||
public class BlockUtils {
|
||||
@@ -437,18 +438,21 @@ public class BlockUtils {
|
||||
/**
|
||||
* Return predecessor on path from 'pathStart' block
|
||||
*/
|
||||
public static @Nullable BlockNode getPrevBlockOnPath(BlockNode block, BlockNode pathStart) {
|
||||
List<BlockNode> preds = block.getPredecessors();
|
||||
if (preds.contains(pathStart)) {
|
||||
public static @Nullable BlockNode getPrevBlockOnPath(MethodNode mth, BlockNode block, BlockNode pathStart) {
|
||||
BlockSet preds = BlockSet.from(mth, block.getPredecessors());
|
||||
if (preds.get(pathStart)) {
|
||||
return pathStart;
|
||||
}
|
||||
Set<BlockNode> path = getAllPathsBlocks(pathStart, block);
|
||||
for (BlockNode p : preds) {
|
||||
if (path.contains(p)) {
|
||||
return p;
|
||||
DFSIteration dfs = new DFSIteration(mth, pathStart, BlockNode::getCleanSuccessors);
|
||||
while (true) {
|
||||
BlockNode next = dfs.next();
|
||||
if (next == null) {
|
||||
return null;
|
||||
}
|
||||
if (preds.get(next)) {
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -515,24 +519,13 @@ public class BlockUtils {
|
||||
|
||||
private static void visitDFS(MethodNode mth, BlockNode startBlock,
|
||||
Function<BlockNode, List<BlockNode>> nextFunc, Consumer<BlockNode> visitor) {
|
||||
BlockSet visited = new BlockSet(mth);
|
||||
Deque<BlockNode> queue = new ArrayDeque<>();
|
||||
queue.addLast(startBlock);
|
||||
visited.set(startBlock);
|
||||
DFSIteration dfsIteration = new DFSIteration(mth, startBlock, nextFunc);
|
||||
while (true) {
|
||||
BlockNode current = queue.pollLast();
|
||||
if (current == null) {
|
||||
BlockNode next = dfsIteration.next();
|
||||
if (next == null) {
|
||||
return;
|
||||
}
|
||||
visitor.accept(current);
|
||||
List<BlockNode> nextBlocks = nextFunc.apply(current);
|
||||
int count = nextBlocks.size();
|
||||
for (int i = count - 1; i >= 0; i--) { // to preserve order in queue
|
||||
BlockNode next = nextBlocks.get(i);
|
||||
if (!visited.checkAndSet(next)) {
|
||||
queue.addLast(next);
|
||||
}
|
||||
}
|
||||
visitor.accept(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package jadx.core.utils.blocks;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
|
||||
public class DFSIteration {
|
||||
private final Function<BlockNode, List<BlockNode>> nextFunc;
|
||||
private final Deque<BlockNode> queue;
|
||||
private final BlockSet visited;
|
||||
|
||||
public DFSIteration(MethodNode mth, BlockNode startBlock, Function<BlockNode, List<BlockNode>> next) {
|
||||
nextFunc = next;
|
||||
queue = new ArrayDeque<>();
|
||||
visited = new BlockSet(mth);
|
||||
queue.addLast(startBlock);
|
||||
visited.set(startBlock);
|
||||
}
|
||||
|
||||
public @Nullable BlockNode next() {
|
||||
BlockNode current = queue.pollLast();
|
||||
if (current == null) {
|
||||
return null;
|
||||
}
|
||||
List<BlockNode> nextBlocks = nextFunc.apply(current);
|
||||
int count = nextBlocks.size();
|
||||
for (int i = count - 1; i >= 0; i--) { // to preserve order in queue
|
||||
BlockNode next = nextBlocks.get(i);
|
||||
if (!visited.checkAndSet(next)) {
|
||||
queue.addLast(next);
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package jadx.tests.integration.others;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestConstructorBranched2 extends SmaliTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
disableCompilation();
|
||||
assertThat(getClassNodeFromSmali())
|
||||
.code()
|
||||
.countString(3, "new StringBuilder()");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
.class public Lothers/TestConstructorBranched2;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.method private test(Ljava/util/List;)Ljava/lang/String;
|
||||
.locals 12
|
||||
iget-boolean v1, p0, Landroidx/gridlayout/widget/GridLayout$Axis;->horizontal:Z
|
||||
const/4 v2, 0x1
|
||||
if-eqz v1, :cond_0
|
||||
const-string/jumbo v1, "x"
|
||||
goto :goto_0
|
||||
|
||||
:cond_0
|
||||
const-string/jumbo v1, "y"
|
||||
|
||||
:goto_0
|
||||
new-instance v3, Ljava/lang/StringBuilder;
|
||||
invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V
|
||||
const/4 v4, 0x1
|
||||
invoke-interface {p1}, Ljava/util/List;->iterator()Ljava/util/Iterator;
|
||||
move-result-object v5
|
||||
const/16 v6, 0x98
|
||||
|
||||
:goto_1
|
||||
invoke-interface {v5}, Ljava/util/Iterator;->hasNext()Z
|
||||
move-result v6
|
||||
if-eqz v6, :cond_3
|
||||
invoke-interface {v5}, Ljava/util/Iterator;->next()Ljava/lang/Object;
|
||||
move-result-object v6
|
||||
check-cast v6, Landroidx/gridlayout/widget/GridLayout$Arc;
|
||||
if-eqz v4, :cond_1
|
||||
const/4 v4, 0x0
|
||||
goto :goto_2
|
||||
|
||||
:cond_1
|
||||
const-string v7, ", "
|
||||
invoke-virtual {v3, v7}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v3
|
||||
|
||||
:goto_2
|
||||
iget-object v7, v6, Landroidx/gridlayout/widget/GridLayout$Arc;->span:Landroidx/gridlayout/widget/GridLayout$Interval;
|
||||
iget v7, v7, Landroidx/gridlayout/widget/GridLayout$Interval;->min:I
|
||||
iget-object v8, v6, Landroidx/gridlayout/widget/GridLayout$Arc;->span:Landroidx/gridlayout/widget/GridLayout$Interval;
|
||||
iget v8, v8, Landroidx/gridlayout/widget/GridLayout$Interval;->max:I
|
||||
iget-object v9, v6, Landroidx/gridlayout/widget/GridLayout$Arc;->value:Landroidx/gridlayout/widget/GridLayout$MutableInt;
|
||||
iget v9, v9, Landroidx/gridlayout/widget/GridLayout$MutableInt;->value:I
|
||||
const-string v10, "-"
|
||||
new-instance v11, Ljava/lang/StringBuilder;
|
||||
if-ge v7, v8, :cond_2
|
||||
invoke-direct {v11}, Ljava/lang/StringBuilder;-><init>()V
|
||||
invoke-virtual {v11, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v11
|
||||
invoke-virtual {v11, v8}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v11
|
||||
invoke-virtual {v11, v10}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10, v7}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
const-string v11, ">="
|
||||
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10, v9}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
|
||||
move-result-object v10
|
||||
goto :goto_3
|
||||
|
||||
:cond_2
|
||||
invoke-direct {v11}, Ljava/lang/StringBuilder;-><init>()V
|
||||
invoke-virtual {v11, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v11
|
||||
invoke-virtual {v11, v7}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v11
|
||||
invoke-virtual {v11, v10}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10, v8}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
const-string v11, "<="
|
||||
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
neg-int v11, v9
|
||||
invoke-virtual {v10, v11}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
|
||||
move-result-object v10
|
||||
invoke-virtual {v10}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
|
||||
move-result-object v10
|
||||
|
||||
:goto_3
|
||||
invoke-virtual {v3, v10}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
|
||||
goto/16 :goto_1
|
||||
|
||||
:cond_3
|
||||
invoke-virtual {v3}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
|
||||
move-result-object v5
|
||||
return-object v5
|
||||
.end method
|
||||
Reference in New Issue
Block a user