diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java index 371c85bb1..c9c44378d 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/CodeShrinker.java @@ -23,8 +23,6 @@ import java.util.List; import java.util.ListIterator; import java.util.Set; -import org.jetbrains.annotations.Nullable; - public class CodeShrinker extends AbstractVisitor { @Override @@ -38,6 +36,7 @@ public class CodeShrinker extends AbstractVisitor { } for (BlockNode block : mth.getBasicBlocks()) { shrinkBlock(mth, block); + simplifyMoveInsns(block); } } @@ -231,53 +230,28 @@ public class CodeShrinker extends AbstractVisitor { if (assignBlock != null && assignInsn != arg.getParentInsn() && canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) { - if (inline(arg, assignInsn, assignBlock, mth)) { - InsnList.remove(assignBlock, assignInsn); - } + inline(arg, assignInsn, assignBlock); } } } } if (!wrapList.isEmpty()) { for (WrapInfo wrapInfo : wrapList) { - inline(wrapInfo.getArg(), wrapInfo.getInsn(), block, mth); - } - for (WrapInfo wrapInfo : wrapList) { - insnList.remove(wrapInfo.getInsn()); + inline(wrapInfo.getArg(), wrapInfo.getInsn(), block); } } } - private static boolean inline(RegisterArg arg, InsnNode insn, @Nullable BlockNode block, MethodNode mth) { + private static boolean inline(RegisterArg arg, InsnNode insn, BlockNode block) { InsnNode parentInsn = arg.getParentInsn(); - // replace move instruction if needed - if (parentInsn != null) { - switch (parentInsn.getType()) { - case MOVE: { - if (block == null) { - block = BlockUtils.getBlockByInsn(mth, parentInsn); - } - if (block != null) { - int index = InsnList.getIndex(block.getInstructions(), parentInsn); - if (index != -1) { - insn.setResult(parentInsn.getResult()); - insn.copyAttributesFrom(parentInsn); - insn.setOffset(parentInsn.getOffset()); - - block.getInstructions().set(index, insn); - return true; - } - } - break; - } - case RETURN: { - parentInsn.setSourceLine(insn.getSourceLine()); - break; - } - } + if (parentInsn != null && parentInsn.getType() == InsnType.RETURN) { + parentInsn.setSourceLine(insn.getSourceLine()); } - // simple case - return arg.wrapInstruction(insn) != null; + boolean replaced = arg.wrapInstruction(insn) != null; + if (replaced) { + InsnList.remove(block, insn); + } + return replaced; } private static boolean canMoveBetweenBlocks(InsnNode assignInsn, BlockNode assignBlock, @@ -320,4 +294,24 @@ public class CodeShrinker extends AbstractVisitor { } throw new JadxRuntimeException("Can't process instruction move : " + assignBlock); } + + private static void simplifyMoveInsns(BlockNode block) { + List insns = block.getInstructions(); + int size = insns.size(); + for (int i = 0; i < size; i++) { + InsnNode insn = insns.get(i); + if (insn.getType() == InsnType.MOVE) { + // replace 'move' with wrapped insn + InsnArg arg = insn.getArg(0); + if (arg.isInsnWrap()) { + InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); + wrapInsn.setResult(insn.getResult()); + wrapInsn.copyAttributesFrom(insn); + wrapInsn.setOffset(insn.getOffset()); + wrapInsn.remove(AFlag.WRAPPED); + block.getInstructions().set(i, wrapInsn); + } + } + } + } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/inline/TestIssue86.java b/jadx-core/src/test/java/jadx/tests/integration/inline/TestIssue86.java new file mode 100644 index 000000000..d29baa9dc --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/inline/TestIssue86.java @@ -0,0 +1,116 @@ +package jadx.tests.integration.inline; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.IntegrationTest; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import static jadx.tests.api.utils.JadxMatchers.containsOne; +import static org.junit.Assert.assertThat; + +public class TestIssue86 extends IntegrationTest { + + public static class TestCls { + private static final String SERVER_ERR = "server-err"; + private static final String NOT_FOUND = "not-found"; + private static final String LIST_TAG = "list-tag"; + private static final String TEMP_TAG = "temp-tag"; + private static final String MIN_TAG = "min-tag"; + private static final String MAX_TAG = "max-tag"; + private static final String MILLIS_TAG = "millis-tag"; + private static final String WEATHER_TAG = "weather-tag"; + private static final String DESC_TAG = "desc-tag"; + + private List test(String response) { + List reportList = new ArrayList(); + try { + System.out.println(response); + if (response != null + && (response.startsWith(SERVER_ERR) + || response.startsWith(NOT_FOUND))) { + return reportList; + } + JSONObject jsonObj = new JSONObject(response); + JSONArray days = jsonObj.getJSONArray(LIST_TAG); + for (int i = 0; i < days.length(); i++) { + JSONObject c = days.getJSONObject(i); + long millis = c.getLong(MILLIS_TAG); + JSONObject temp = c.getJSONObject(TEMP_TAG); + String max = temp.getString(MAX_TAG); + String min = temp.getString(MIN_TAG); + JSONArray weather = c.getJSONArray(WEATHER_TAG); + String weatherDesc = weather.getJSONObject(0).getString(DESC_TAG); + Day d = new Day(); + d.setMilis(millis); + d.setMinTmp(min); + d.setMaxTmp(max); + d.setWeatherDesc(weatherDesc); + reportList.add(d); + } + } catch (JSONException e) { + e.printStackTrace(); + } + return reportList; + } + + private static class Day { + public void setMilis(long milis) { + } + + public void setMinTmp(String min) { + } + + public void setMaxTmp(String max) { + } + + public void setWeatherDesc(String weatherDesc) { + } + } + + private static class JSONObject { + public JSONObject(String response) { + } + + public JSONArray getJSONArray(String tag) throws JSONException { + return null; + } + + public JSONObject getJSONObject(String tag) throws JSONException { + return null; + } + + public String getString(String tag) throws JSONException { + return null; + } + + public long getLong(String tag) throws JSONException { + return 0; + } + } + + private class JSONArray { + public JSONObject getJSONObject(int i) throws JSONException { + return null; + } + + public int length() { + return 0; + } + } + + private class JSONException extends Exception { + private static final long serialVersionUID = -4358405506584551910L; + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsOne("response.startsWith(NOT_FOUND)")); + } +}