Skip to content

Commit

Permalink
fix: comment out instructions before super call in constructor (#685)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 3, 2019
1 parent 0f5fd4e commit c6c54f9
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 1 deletion.
3 changes: 3 additions & 0 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ protected void makeInsn(InsnNode insn, CodeWriter code, Flags flag) throws Codeg
if (attachInsns) {
code.attachLineAnnotation(insn);
}
if (insn.contains(AFlag.COMMENT_OUT)) {
code.add("// ");
}
}
if (insn.getResult() != null) {
SSAVar var = insn.getResult().getSVar();
Expand Down
4 changes: 3 additions & 1 deletion jadx-core/src/main/java/jadx/core/dex/attributes/AFlag.java
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@

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;
Expand All @@ -33,6 +38,8 @@
)
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();
Expand All @@ -48,6 +55,7 @@ public void visit(MethodNode mth) throws JadxException {
removeParenthesis(block);
modifyArith(block);
}
commentOutInsnsBeforeSuper(mth);
}

private static void removeInstructions(BlockNode block) {
Expand Down Expand Up @@ -171,4 +179,33 @@ private static void modifyArith(BlockNode block) {
}
}
}

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);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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);"));
}
}
14 changes: 14 additions & 0 deletions jadx-core/src/test/smali/others/TestInsnsBeforeSuper/A.smali
Original file line number Diff line number Diff line change
@@ -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
30 changes: 30 additions & 0 deletions jadx-core/src/test/smali/others/TestInsnsBeforeSuper/B.smali
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c6c54f9

Please sign in to comment.