diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index 380862d6b..c3cc1bd9e 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -302,7 +302,7 @@ public class ClassGen { } } MethodGen mthGen; - if (badCode || mth.contains(AType.JADX_ERROR)) { + if (badCode || mth.contains(AType.JADX_ERROR) || fallback) { mthGen = MethodGen.getFallbackMethodGen(mth); } else { mthGen = new MethodGen(this, mth); @@ -313,7 +313,11 @@ public class ClassGen { code.add('{'); code.incIndent(); insertSourceFileInfo(code, mth); - mthGen.addInstructions(code); + if (fallback) { + mthGen.addFallbackMethodCode(code); + } else { + mthGen.addInstructions(code); + } code.decIndent(); code.startLine('}'); } @@ -535,7 +539,7 @@ public class ClassGen { private void insertSourceFileInfo(CodeWriter code, AttrNode node) { SourceFileAttr sourceFileAttr = node.get(AType.SOURCE_FILE); if (sourceFileAttr != null) { - code.startLine("// compiled from: ").add(sourceFileAttr.getFileName()); + code.startLine("/* compiled from: ").add(sourceFileAttr.getFileName()).add(" */"); } } diff --git a/jadx-core/src/main/java/jadx/core/codegen/NameGen.java b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java index d261f021b..1b4473c4f 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/NameGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/NameGen.java @@ -70,7 +70,7 @@ public class NameGen { public String useArg(RegisterArg arg) { String name = arg.getName(); - if (name == null) { + if (name == null || fallback) { return getFallbackName(arg); } return name; @@ -117,10 +117,7 @@ public class NameGen { private String getFallbackName(RegisterArg arg) { String name = arg.getName(); String base = "r" + arg.getRegNum(); - if (name != null && !name.equals("this")) { - return base + "_" + name; - } - return base; + return name != null ? base + "_" + name : base; } private static String makeNameForType(ArgType type) { diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 20be14dd0..6f83c88d7 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -114,6 +114,26 @@ public class MethodNode extends LineAttrNode implements ILoadable { } } + public void checkInstructions() { + List list = new ArrayList(); + for (InsnNode insnNode : instructions) { + if (insnNode == null) { + continue; + } + list.clear(); + RegisterArg resultArg = insnNode.getResult(); + if (resultArg != null) { + list.add(resultArg); + } + insnNode.getRegisterArgs(list); + for (int i = 0, listSize = list.size(); i < listSize; i++) { + if (list.get(i).getRegNum() >= regsCount) { + throw new JadxRuntimeException("Incorrect register number in instruction: " + insnNode); + } + } + } + } + private void initMethodTypes() { if (!parseSignature()) { retType = mthInfo.getReturnType(); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java index bb34da218..9056b3c0c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/BlockMakerVisitor.java @@ -45,6 +45,8 @@ public class BlockMakerVisitor extends AbstractVisitor { if (mth.isNoCode()) { return; } + mth.checkInstructions(); + mth.initBasicBlocks(); splitBasicBlocks(mth); processBlocksTree(mth); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java b/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java index ac5964bc0..b1ae8da06 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/DepthTraversal.java @@ -1,5 +1,6 @@ package jadx.core.dex.visitors; +import jadx.core.dex.attributes.AType; import jadx.core.dex.nodes.ClassNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.utils.ErrorsCounter; @@ -23,6 +24,9 @@ public class DepthTraversal { } public static void visit(IDexTreeVisitor visitor, MethodNode mth) { + if (mth.contains(AType.JADX_ERROR)) { + return; + } try { visitor.visit(mth); } catch (Throwable e) { diff --git a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java index a67b1963d..7c013f9e1 100644 --- a/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java +++ b/jadx-core/src/test/java/jadx/tests/api/IntegrationTest.java @@ -335,13 +335,15 @@ public abstract class IntegrationTest extends TestUtils { return files; } - public void noDebugInfo() { + protected void noDebugInfo() { this.withDebugInfo = false; } - // Try to make test class compilable - @Deprecated - public void disableCompilation() { + protected void setFallback() { + this.isFallback = true; + } + + protected void disableCompilation() { this.compile = false; } @@ -351,12 +353,6 @@ public abstract class IntegrationTest extends TestUtils { this.outputCFG = true; } - // Use only for debug purpose - @Deprecated - protected void setFallback() { - this.isFallback = true; - } - // Use only for debug purpose @Deprecated protected void notDeleteTmpJar() { diff --git a/jadx-core/src/test/java/jadx/tests/api/SmaliTest.java b/jadx-core/src/test/java/jadx/tests/api/SmaliTest.java index 3e8e5b6c0..2d4013eab 100644 --- a/jadx-core/src/test/java/jadx/tests/api/SmaliTest.java +++ b/jadx-core/src/test/java/jadx/tests/api/SmaliTest.java @@ -25,7 +25,7 @@ public class SmaliTest extends IntegrationTest { return getClassNodeFromFile(outDex, fullClsName); } - private File getSmaliFile(String clsName) { + private static File getSmaliFile(String clsName) { File smaliFile = new File(SMALI_TESTS_DIR, clsName + SMALI_TESTS_EXT); if (smaliFile.exists()) { return smaliFile; @@ -38,7 +38,7 @@ public class SmaliTest extends IntegrationTest { return null; } - public boolean compileSmali(File input, File output) { + private static boolean compileSmali(File input, File output) { List args = new ArrayList(); args.add(input.getAbsolutePath()); diff --git a/jadx-core/src/test/java/jadx/tests/integration/fallback/TestFallbackMode.java b/jadx-core/src/test/java/jadx/tests/integration/fallback/TestFallbackMode.java new file mode 100644 index 000000000..19ca15275 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/fallback/TestFallbackMode.java @@ -0,0 +1,37 @@ +package jadx.tests.integration.fallback; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; + +public class TestFallbackMode extends IntegrationTest { + + public static class TestCls { + + public int test(int a) { + while (a < 10) { + a++; + } + return a; + } + } + + @Test + public void test() { + setFallback(); + disableCompilation(); + + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsString("public int test(int r2) {")); + assertThat(code, containsString("r1_this = this;")); + assertThat(code, containsString("L_0x0004:")); + assertThat(code, not(containsString("throw new UnsupportedOperationException"))); + } +}