diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java index 961d4daf0682cc12e0fc0e2de16d67cf4e2dc60e..b2d92231aa2f19bd669308d0a38d7938a1396806 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ReSugarCode.java @@ -4,8 +4,6 @@ import java.util.List; import java.util.stream.Collectors; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; @@ -44,8 +42,6 @@ import jadx.core.utils.exceptions.JadxException; ) public class ReSugarCode extends AbstractVisitor { - private static final Logger LOG = LoggerFactory.getLogger(ReSugarCode.class); - @Override public boolean visit(ClassNode cls) throws JadxException { initClsEnumMap(cls); @@ -57,55 +53,57 @@ public class ReSugarCode extends AbstractVisitor { if (mth.isNoCode()) { return; } + boolean changed = false; InsnRemover remover = new InsnRemover(mth); for (BlockNode block : mth.getBasicBlocks()) { remover.setBlock(block); List instructions = block.getInstructions(); int size = instructions.size(); for (int i = 0; i < size; i++) { - process(mth, instructions, i, remover); + changed |= process(mth, instructions, i, remover); } remover.perform(); } + if (changed) { + CodeShrinkVisitor.shrinkMethod(mth); + } } - private static void process(MethodNode mth, List instructions, int i, InsnRemover remover) { + private static boolean process(MethodNode mth, List instructions, int i, InsnRemover remover) { InsnNode insn = instructions.get(i); if (insn.contains(AFlag.REMOVE)) { - return; + return false; } switch (insn.getType()) { case NEW_ARRAY: - processNewArray(mth, (NewArrayNode) insn, instructions, remover); - break; + return processNewArray(mth, (NewArrayNode) insn, instructions, remover); case SWITCH: - processEnumSwitch(mth, (SwitchInsn) insn); - break; + return processEnumSwitch(mth, (SwitchInsn) insn); default: - break; + return false; } } /** * Replace new-array and sequence of array-put to new filled-array instruction. */ - private static void processNewArray(MethodNode mth, NewArrayNode newArrayInsn, + private static boolean processNewArray(MethodNode mth, NewArrayNode newArrayInsn, List instructions, InsnRemover remover) { InsnArg arrLenArg = newArrayInsn.getArg(0); if (!arrLenArg.isLiteral()) { - return; + return false; } int len = (int) ((LiteralArg) arrLenArg).getLiteral(); if (len == 0) { - return; + return false; } RegisterArg arrArg = newArrayInsn.getResult(); SSAVar ssaVar = arrArg.getSVar(); List useList = ssaVar.getUseList(); if (useList.size() < len) { - return; + return false; } // check sequential array put with increasing index int putIndex = 0; @@ -118,17 +116,15 @@ public class ReSugarCode extends AbstractVisitor { } } if (putIndex != len) { - return; + return false; } List arrPuts = useList.subList(0, len).stream().map(InsnArg::getParentInsn).collect(Collectors.toList()); // check that all puts in current block for (InsnNode arrPut : arrPuts) { int index = InsnList.getIndex(instructions, arrPut); if (index == -1) { - if (LOG.isDebugEnabled()) { - LOG.debug("TODO: APUT found in different block: {}, mth: {}", arrPut, mth); - } - return; + mth.addDebugComment("Can't convert new array creation: APUT found in different block: " + arrPut); + return false; } } @@ -146,6 +142,7 @@ public class ReSugarCode extends AbstractVisitor { InsnNode lastPut = Utils.last(arrPuts); int replaceIndex = InsnList.getIndex(instructions, lastPut); instructions.set(replaceIndex, filledArr); + return true; } private static boolean checkPutInsn(MethodNode mth, InsnNode insn, RegisterArg arrArg, int putIndex) { @@ -164,43 +161,44 @@ public class ReSugarCode extends AbstractVisitor { return false; } - private static void processEnumSwitch(MethodNode mth, SwitchInsn insn) { + private static boolean processEnumSwitch(MethodNode mth, SwitchInsn insn) { InsnArg arg = insn.getArg(0); if (!arg.isInsnWrap()) { - return; + return false; } InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); if (wrapInsn.getType() != InsnType.AGET) { - return; + return false; } EnumMapInfo enumMapInfo = checkEnumMapAccess(mth.root(), wrapInsn); if (enumMapInfo == null) { - return; + return false; } FieldNode enumMapField = enumMapInfo.getMapField(); InsnArg invArg = enumMapInfo.getArg(); EnumMapAttr.KeyValueMap valueMap = getEnumMap(mth, enumMapField); if (valueMap == null) { - return; + return false; } int caseCount = insn.getKeys().length; for (int i = 0; i < caseCount; i++) { Object key = insn.getKey(i); Object newKey = valueMap.get(key); if (newKey == null) { - return; + return false; } } // replace confirmed if (!insn.replaceArg(arg, invArg)) { - return; + return false; } for (int i = 0; i < caseCount; i++) { insn.modifyKey(i, valueMap.get(insn.getKey(i))); } enumMapField.add(AFlag.DONT_GENERATE); checkAndHideClass(enumMapField.getParentClass()); + return true; } private static void initClsEnumMap(ClassNode enumCls) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/invoke/TestVarArg2.java b/jadx-core/src/test/java/jadx/tests/integration/invoke/TestVarArg2.java new file mode 100644 index 0000000000000000000000000000000000000000..7a13e6037d7c07c26252c6b83b8d433ef9ea2f0b --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/invoke/TestVarArg2.java @@ -0,0 +1,27 @@ +package jadx.tests.integration.invoke; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestVarArg2 extends IntegrationTest { + + @SuppressWarnings("ConstantConditions") + public static class TestCls { + protected static boolean b1; + protected static final boolean IS_VALID = b1 && isValid("test"); + + private static boolean isValid(String... string) { + return false; + } + } + + @Test + public void test() { + assertThat(getClassNode(TestCls.class)) + .code() + .containsOne("isValid(\"test\")"); // TODO: .containsOne("b1 && isValid(\"test\")"); + } +}