fix: comment out instructions before super call in constructor (#685)
This commit is contained in:
@@ -227,6 +227,9 @@ public class InsnGen {
|
||||
if (attachInsns) {
|
||||
code.attachLineAnnotation(insn);
|
||||
}
|
||||
if (insn.contains(AFlag.COMMENT_OUT)) {
|
||||
code.add("// ");
|
||||
}
|
||||
}
|
||||
if (insn.getResult() != null) {
|
||||
SSAVar var = insn.getResult().getSVar();
|
||||
|
||||
@@ -15,9 +15,11 @@ public enum AFlag {
|
||||
DONT_WRAP,
|
||||
DONT_INLINE,
|
||||
DONT_GENERATE, // process as usual, but don't output to generated code
|
||||
COMMENT_OUT, // process as usual, but comment insn in generated code
|
||||
REMOVE, // can be completely removed
|
||||
|
||||
RESTART_CODEGEN,
|
||||
DONT_RENAME, // do not rename during deobfuscation
|
||||
REMOVE, // can be completely removed
|
||||
ADDED_TO_REGION,
|
||||
|
||||
FINALLY_INSNS,
|
||||
|
||||
@@ -2,21 +2,26 @@ package jadx.core.dex.visitors;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.instructions.ArithNode;
|
||||
import jadx.core.dex.instructions.ArithOp;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.InsnWrapArg;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
import jadx.core.dex.instructions.mods.ConstructorInsn;
|
||||
import jadx.core.dex.instructions.mods.TernaryInsn;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.IBlock;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.regions.conditions.IfCondition;
|
||||
import jadx.core.dex.regions.conditions.IfCondition.Mode;
|
||||
import jadx.core.dex.visitors.regions.AbstractRegionVisitor;
|
||||
import jadx.core.dex.visitors.regions.DepthRegionTraversal;
|
||||
import jadx.core.dex.visitors.regions.variables.ProcessVariables;
|
||||
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
|
||||
import jadx.core.utils.exceptions.JadxException;
|
||||
@@ -33,6 +38,8 @@ import jadx.core.utils.exceptions.JadxException;
|
||||
)
|
||||
public class PrepareForCodeGen extends AbstractVisitor {
|
||||
|
||||
public static final SuperCallRegionVisitor SUPER_CALL_REGION_VISITOR = new SuperCallRegionVisitor();
|
||||
|
||||
@Override
|
||||
public void visit(MethodNode mth) throws JadxException {
|
||||
List<BlockNode> blocks = mth.getBasicBlocks();
|
||||
@@ -48,6 +55,7 @@ public class PrepareForCodeGen extends AbstractVisitor {
|
||||
removeParenthesis(block);
|
||||
modifyArith(block);
|
||||
}
|
||||
commentOutInsnsBeforeSuper(mth);
|
||||
}
|
||||
|
||||
private static void removeInstructions(BlockNode block) {
|
||||
@@ -171,4 +179,33 @@ public class PrepareForCodeGen extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void commentOutInsnsBeforeSuper(MethodNode mth) {
|
||||
if (mth.isConstructor() && !Objects.equals(mth.getParentClass().getSuperClass(), ArgType.OBJECT)) {
|
||||
DepthRegionTraversal.traverse(mth, SUPER_CALL_REGION_VISITOR);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SuperCallRegionVisitor extends AbstractRegionVisitor {
|
||||
@Override
|
||||
public void processBlock(MethodNode mth, IBlock container) {
|
||||
for (InsnNode insn : container.getInstructions()) {
|
||||
InsnType insnType = insn.getType();
|
||||
if ((insnType == InsnType.CONSTRUCTOR) && ((ConstructorInsn) insn).isSuper()) {
|
||||
// found super call
|
||||
commentOutInsns(container, insn);
|
||||
// TODO: process all previous regions (in case of branching before super call)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void commentOutInsns(IBlock container, InsnNode superInsn) {
|
||||
for (InsnNode insn : container.getInstructions()) {
|
||||
if (insn == superInsn) {
|
||||
break;
|
||||
}
|
||||
insn.add(AFlag.COMMENT_OUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package jadx.tests.integration.others;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class TestInsnsBeforeSuper extends SmaliTest {
|
||||
// @formatter:off
|
||||
/*
|
||||
public class A {
|
||||
public A(String s) {
|
||||
}
|
||||
}
|
||||
|
||||
public class B extends A {
|
||||
public B(String str) {
|
||||
checkNull(str);
|
||||
super(str);
|
||||
}
|
||||
|
||||
public void checkNull(Object o) {
|
||||
if (o == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
// @formatter:on
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNodeFromSmaliFiles("B");
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("// checkNull(str);"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
.class public Lothers/A;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>(Ljava/lang/String;)V
|
||||
.registers 3
|
||||
|
||||
.prologue
|
||||
|
||||
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
@@ -0,0 +1,30 @@
|
||||
.class public Lothers/B;
|
||||
.super Lothers/A;
|
||||
|
||||
|
||||
# direct methods
|
||||
.method public constructor <init>(Ljava/lang/String;)V
|
||||
.registers 3
|
||||
|
||||
.prologue
|
||||
invoke-static {p1}, Lothers/B;->checkNull(Ljava/lang/Object;)V
|
||||
|
||||
invoke-direct {p0, p1}, Lothers/A;-><init>(Ljava/lang/String;)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
|
||||
.method public static checkNull(Ljava/lang/Object;)V
|
||||
.registers 3
|
||||
|
||||
.prologue
|
||||
if-nez p0, :cond_8
|
||||
|
||||
new-instance v0, Ljava/lang/NullPointerException;
|
||||
invoke-direct {v0}, Ljava/lang/NullPointerException;-><init>()V
|
||||
throw v0
|
||||
|
||||
:cond_8
|
||||
return-void
|
||||
.end method
|
||||
Reference in New Issue
Block a user