fix: IfRegionMaker find the wrong outBlock (PR #2385)

* IfRegionMaker find wrong out block

* fix: test codes fail because of the previous commit
This commit is contained in:
ewt45
2024-12-30 21:42:03 +08:00
committed by GitHub
parent f4849d67cf
commit 84e211b809
4 changed files with 187 additions and 14 deletions
@@ -178,6 +178,8 @@ final class IfRegionMaker {
info.setOutBlock(null);
return info;
}
// init outblock, which will be used in isBadBranchBlock to compare with branch block
info.setOutBlock(BlockUtils.getPathCross(mth, thenBlock, elseBlock));
boolean badThen = isBadBranchBlock(info, thenBlock);
boolean badElse = isBadBranchBlock(info, elseBlock);
if (badThen && badElse) {
@@ -193,8 +195,6 @@ final class IfRegionMaker {
info = IfInfo.invert(info);
info = new IfInfo(info, elseBlock, null);
info.setOutBlock(thenBlock);
} else {
info.setOutBlock(BlockUtils.getPathCross(mth, thenBlock, elseBlock));
}
if (BlockUtils.isBackEdge(block, info.getOutBlock())) {
info.setOutBlock(null);
@@ -219,6 +219,10 @@ final class IfRegionMaker {
}
}
}
// if branch block itself is outblock
if (info.getOutBlock() != null) {
return block == info.getOutBlock();
}
return !allPathsFromIf(block, info);
}
@@ -761,18 +761,22 @@ public class BlockUtils {
/**
* Return common cross block for input set.
*
* @return null if cross is a method exit block.
* @return could be one of the giving blocks. null if cross is a method exit block.
*/
@Nullable
public static BlockNode getPathCross(MethodNode mth, Collection<BlockNode> blocks) {
BitSet domFrontBS = newBlocksBitSet(mth);
BitSet tmpBS = newBlocksBitSet(mth); // store block itself and its domFrontier
boolean first = true;
for (BlockNode b : blocks) {
tmpBS.clear();
tmpBS.set(b.getId());
tmpBS.or(b.getDomFrontier());
if (first) {
domFrontBS.or(b.getDomFrontier());
domFrontBS.or(tmpBS);
first = false;
} else {
domFrontBS.and(b.getDomFrontier());
domFrontBS.and(tmpBS);
}
}
domFrontBS.clear(mth.getExitBlock().getId());
@@ -790,7 +794,7 @@ public class BlockUtils {
mth.getLoops().forEach(l -> excluded.set(l.getStart().getId()));
if (!mth.isNoExceptionHandlers()) {
// exclude exception handlers paths
mth.getExceptionHandlers().forEach(h -> mergeExcHandlerDomFrontier(mth, h, excluded));
mth.getExceptionHandlers().forEach(h -> addExcHandler(mth, h, excluded));
}
domFrontBS.andNot(excluded);
oneBlock = bitSetToOneBlock(mth, domFrontBS);
@@ -805,7 +809,6 @@ public class BlockUtils {
BitSet domFrontier = block.getDomFrontier();
if (!domFrontier.isEmpty()) {
combinedDF.or(domFrontier);
combinedDF.clear(block.getId());
}
});
combinedDF.andNot(excluded);
@@ -827,18 +830,13 @@ public class BlockUtils {
}
}
private static void mergeExcHandlerDomFrontier(MethodNode mth, ExceptionHandler handler, BitSet set) {
private static void addExcHandler(MethodNode mth, ExceptionHandler handler, BitSet set) {
BlockNode handlerBlock = handler.getHandlerBlock();
if (handlerBlock == null) {
mth.addDebugComment("Null handler block in: " + handler);
return;
}
BitSet domFrontier = handlerBlock.getDomFrontier();
if (domFrontier == null) {
mth.addDebugComment("Null dom frontier in handler: " + handler);
return;
}
set.or(domFrontier);
set.set(handlerBlock.getId());
}
public static BlockNode getPathCross(MethodNode mth, BlockNode b1, BlockNode b2) {
@@ -0,0 +1,22 @@
package jadx.tests.integration.conditions;
import org.junit.jupiter.api.Test;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
/**
* Issue #2384
*/
public class TestOutBlock extends SmaliTest {
@Test
public void test() {
allowWarnInCode();
disableCompilation();
assertThat(getClassNodeFromSmali())
.code()
.containsOne("setContentView");
}
}
@@ -0,0 +1,149 @@
.class public Lconditions/TestOutBlock;
.super Lcom/eltechs/axs/activities/FrameworkActivity;
.method protected onCreate(Landroid/os/Bundle;)V
.registers 9
.line 98
invoke-super {p0, p1}, Lcom/eltechs/axs/activities/FrameworkActivity;->onCreate(Landroid/os/Bundle;)V
.line 101
invoke-virtual {p0}, Lconditions/TestOutBlock;->getApplicationState()Lcom/eltechs/axs/applicationState/ApplicationStateBase;
move-result-object p1
.line 102
invoke-interface {p1}, Lcom/eltechs/axs/applicationState/ApplicationStateBase;->getEnvironment()Lcom/eltechs/axs/environmentService/AXSEnvironment;
move-result-object v0
const-class v1, Lcom/eltechs/axs/environmentService/components/XServerComponent;
invoke-virtual {v0, v1}, Lcom/eltechs/axs/environmentService/AXSEnvironment;->getComponent(Ljava/lang/Class;)Lcom/eltechs/axs/environmentService/EnvironmentComponent;
move-result-object v0
check-cast v0, Lcom/eltechs/axs/environmentService/components/XServerComponent;
.line 103
invoke-virtual {p0}, Lconditions/TestOutBlock;->getIntent()Landroid/content/Intent;
move-result-object v1
const-string v2, "facadeclass"
invoke-virtual {v1, v2}, Landroid/content/Intent;->getSerializableExtra(Ljava/lang/String;)Ljava/io/Serializable;
move-result-object v1
check-cast v1, Ljava/lang/Class;
if-eqz v1, :cond_46
const/4 v2, 0x2
const/4 v3, 0x0
.line 108
:try_start_23
new-array v4, v2, [Ljava/lang/Class;
const-class v5, Lcom/eltechs/axs/xserver/XServer;
aput-object v5, v4, v3
const-class v5, Lcom/eltechs/axs/applicationState/ApplicationStateBase;
const/4 v6, 0x1
aput-object v5, v4, v6
invoke-virtual {v1, v4}, Ljava/lang/Class;->getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
move-result-object v1
.line 109
new-array v2, v2, [Ljava/lang/Object;
invoke-virtual {v0}, Lcom/eltechs/axs/environmentService/components/XServerComponent;->getXServer()Lcom/eltechs/axs/xserver/XServer;
move-result-object v4
aput-object v4, v2, v3
aput-object p1, v2, v6
invoke-virtual {v1, v2}, Ljava/lang/reflect/Constructor;->newInstance([Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v1
check-cast v1, Lcom/eltechs/axs/xserver/ViewFacade;
:try_end_42
.catch Ljava/lang/Exception; {:try_start_23 .. :try_end_42} :catch_43
goto :goto_47
.line 112
:catch_43
invoke-static {v3}, Lcom/eltechs/axs/helpers/Assert;->state(Z)V
:cond_46
const/4 v1, 0x0
.line 118
:goto_47
invoke-virtual {p0}, Lconditions/TestOutBlock;->getWindow()Landroid/view/Window;
move-result-object v2
const/16 v3, 0x80
invoke-virtual {v2, v3}, Landroid/view/Window;->addFlags(I)V
.line 120
invoke-virtual {p0}, Lconditions/TestOutBlock;->getWindow()Landroid/view/Window;
move-result-object v2
const/high16 v3, 0x400000
invoke-virtual {v2, v3}, Landroid/view/Window;->addFlags(I)V
.line 125
sget v2, Lcom/eltechs/axs/R$layout;->main:I
invoke-virtual {p0, v2}, Lconditions/TestOutBlock;->setContentView(I)V
.line 127
invoke-direct {p0}, Lconditions/TestOutBlock;->checkForSuddenDeath()Z
move-result v2
if-eqz v2, :cond_65
return-void
.line 135
:cond_65
new-instance v2, Lcom/eltechs/axs/widgets/viewOfXServer/ViewOfXServer;
invoke-virtual {v0}, Lcom/eltechs/axs/environmentService/components/XServerComponent;->getXServer()Lcom/eltechs/axs/xserver/XServer;
move-result-object v0
invoke-interface {p1}, Lcom/eltechs/axs/applicationState/ApplicationStateBase;->getXServerViewConfiguration()Lcom/eltechs/axs/configuration/XServerViewConfiguration;
move-result-object p1
invoke-direct {v2, p0, v0, v1, p1}, Lcom/eltechs/axs/widgets/viewOfXServer/ViewOfXServer;-><init>(Landroid/content/Context;Lcom/eltechs/axs/xserver/XServer;Lcom/eltechs/axs/xserver/ViewFacade;Lcom/eltechs/axs/configuration/XServerViewConfiguration;)V
iput-object v2, p0, Lconditions/TestOutBlock;->viewOfXServer:Lcom/eltechs/axs/widgets/viewOfXServer/ViewOfXServer;
.line 137
iget-object p1, p0, Lconditions/TestOutBlock;->periodicIabCheckTimer:Landroid/os/CountDownTimer;
invoke-virtual {p1}, Landroid/os/CountDownTimer;->start()Landroid/os/CountDownTimer;
return-void
.end method