diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index 665ddc946..2b78f0d21 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -132,6 +132,10 @@ public abstract class InsnArg extends Typed { } InsnArg arg = wrapInsnIntoArg(insn); InsnArg oldArg = parent.getArg(i); + if (arg.getType() == ArgType.UNKNOWN) { + // restore arg type if wrapped insn missing result + arg.setType(oldArg.getType()); + } parent.setArg(i, arg); InsnRemover.unbindArgUsage(mth, oldArg); if (unbind) { diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java index 186aa2b19..4ddebdd4c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnWrapArg.java @@ -1,7 +1,5 @@ package jadx.core.dex.instructions.args; -import java.util.Objects; - import org.jetbrains.annotations.NotNull; import jadx.core.dex.instructions.ConstStringNode; @@ -75,10 +73,18 @@ public final class InsnWrapArg extends InsnArg { } @Override - public String toString() { - if (wrappedInsn.getType() == InsnType.CONST_STR && Objects.equals(type, ArgType.STRING)) { + public String toShortString() { + if (wrappedInsn.getType() == InsnType.CONST_STR) { return "(\"" + ((ConstStringNode) wrappedInsn).getString() + "\")"; } - return "(wrap: " + type + " : " + wrappedInsn + ')'; + return "(wrap:" + type + ":" + wrappedInsn.getType() + ')'; + } + + @Override + public String toString() { + if (wrappedInsn.getType() == InsnType.CONST_STR) { + return "(\"" + ((ConstStringNode) wrappedInsn).getString() + "\")"; + } + return "(wrap:" + type + ":" + wrappedInsn + ')'; } } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java index 9516cd09e..b25e4c11c 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/SimplifyVisitor.java @@ -402,7 +402,8 @@ public class SimplifyVisitor extends AbstractVisitor { } } if (!stringArgFound) { - mth.addDebugComment("TODO: convert one arg to string using `String.valueOf()`, args: " + args); + String argStr = Utils.listToString(args, InsnArg::toShortString); + mth.addDebugComment("TODO: convert one arg to string using `String.valueOf()`, args: " + argStr); return null; } @@ -625,7 +626,9 @@ public class SimplifyVisitor extends AbstractVisitor { for (int i = 1; i < argsCount; i++) { concat.addArg(wrap.getArg(i)); } - return ArithNode.oneArgOp(ArithOp.ADD, fArg, InsnArg.wrapArg(concat)); + InsnArg concatArg = InsnArg.wrapArg(concat); + concatArg.setType(ArgType.STRING); + return ArithNode.oneArgOp(ArithOp.ADD, fArg, concatArg); } catch (Exception e) { LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e); } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java index 496abee01..ac503b990 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/shrink/CodeShrinkVisitor.java @@ -3,7 +3,6 @@ package jadx.core.dex.visitors.shrink; import java.util.ArrayList; import java.util.BitSet; import java.util.List; -import java.util.ListIterator; import java.util.Objects; import java.util.Set; @@ -64,12 +63,9 @@ public class CodeShrinkVisitor extends AbstractVisitor { List wrapList = new ArrayList<>(); for (ArgsInfo argsInfo : argsList) { List args = argsInfo.getArgs(); - if (!args.isEmpty()) { - ListIterator it = args.listIterator(args.size()); - while (it.hasPrevious()) { - RegisterArg arg = it.previous(); - checkInline(mth, block, insnList, wrapList, argsInfo, arg); - } + for (int i = args.size() - 1; i >= 0; i--) { + RegisterArg arg = args.get(i); + checkInline(mth, block, insnList, wrapList, argsInfo, arg); } } if (!wrapList.isEmpty()) { diff --git a/jadx-core/src/test/java/jadx/tests/integration/others/TestStringBuilderElimination5.java b/jadx-core/src/test/java/jadx/tests/integration/others/TestStringBuilderElimination5.java new file mode 100644 index 000000000..04d79d979 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/others/TestStringBuilderElimination5.java @@ -0,0 +1,45 @@ +package jadx.tests.integration.others; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestStringBuilderElimination5 extends IntegrationTest { + + public static class TestCls { + @SuppressWarnings("StringConcatenationInLoop") + public static String test(long[] a) { + String s = ""; + final char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + for (int i = a.length - 1; i >= 0; i--) { + s += hexChars[(int) (a[i] >>> 60) & 0x0f]; + s += hexChars[(int) (a[i] >>> 56) & 0x0f]; + s += hexChars[(int) (a[i] >>> 52) & 0x0f]; + s += hexChars[(int) (a[i] >>> 48) & 0x0f]; + s += hexChars[(int) (a[i] >>> 44) & 0x0f]; + s += hexChars[(int) (a[i] >>> 40) & 0x0f]; + s += hexChars[(int) (a[i] >>> 36) & 0x0f]; + s += hexChars[(int) (a[i] >>> 32) & 0x0f]; + s += hexChars[(int) (a[i] >>> 28) & 0x0f]; + s += hexChars[(int) (a[i] >>> 24) & 0x0f]; + s += hexChars[(int) (a[i] >>> 20) & 0x0f]; + s += hexChars[(int) (a[i] >>> 16) & 0x0f]; + s += hexChars[(int) (a[i] >>> 12) & 0x0f]; + s += hexChars[(int) (a[i] >>> 8) & 0x0f]; + s += hexChars[(int) (a[i] >>> 4) & 0x0f]; + s += hexChars[(int) (a[i]) & 0x0f]; + s += " "; + } + return s; + } + } + + @Test + public void test() { + assertThat(getClassNode(TestCls.class)) + .code() + .doesNotContain(".append("); + } +}