From 8052a90d04202667819b20b88f2059db8664edac Mon Sep 17 00:00:00 2001 From: Bob Flavin Date: Wed, 3 Dec 2014 11:58:04 -0500 Subject: [PATCH] Extended string concatenation code to handle arguments in 'new StringBuilder()' constructer, ie 'new StringBuilder("str")' or 'new StringBuilder(String.valueof(varName))' --- .../core/dex/visitors/SimplifyVisitor.java | 95 ++++++++++++------- 1 file changed, 60 insertions(+), 35 deletions(-) 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 6ed8d488..030e9b15 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 @@ -5,6 +5,7 @@ import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.MethodInfo; import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithOp; +import jadx.core.dex.instructions.ConstStringNode; import jadx.core.dex.instructions.IfNode; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; @@ -86,17 +87,6 @@ public class SimplifyVisitor extends AbstractVisitor { } break; - case MOVE: - InsnArg firstArg = insn.getArg(0); - if (firstArg.isLiteral()) { - InsnNode constInsn = new InsnNode(InsnType.CONST, 1); - constInsn.setResult(insn.getResult()); - constInsn.addArg(firstArg); - constInsn.copyAttributesFrom(insn); - return constInsn; - } - break; - default: break; } @@ -134,30 +124,65 @@ public class SimplifyVisitor extends AbstractVisitor { } private static InsnNode convertInvoke(MethodNode mth, InsnNode insn) { - MethodInfo callMth = ((InvokeNode) insn).getCallMth(); - if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER) - && callMth.getShortId().equals(Consts.MTH_TOSTRING_SIGNATURE) - && insn.getArg(0).isInsnWrap()) { - try { - List chain = flattenInsnChain(insn); - if (chain.size() > 1 && chain.get(0).getType() == InsnType.CONSTRUCTOR) { - ConstructorInsn constr = (ConstructorInsn) chain.get(0); - if (constr.getClassType().getFullName().equals(Consts.CLASS_STRING_BUILDER) - && constr.getArgsCount() == 0) { - int len = chain.size(); - InsnNode concatInsn = new InsnNode(InsnType.STR_CONCAT, len - 1); - for (int i = 1; i < len; i++) { - concatInsn.addArg(chain.get(i).getArg(1)); - } - concatInsn.setResult(insn.getResult()); - return concatInsn; - } - } - } catch (Throwable e) { - LOG.debug("Can't convert string concatenation: {} insn: {}", mth, insn, e); - } - } - return null; + MethodInfo callMth = ((InvokeNode) insn).getCallMth(); + + // If this is a 'new StringBuilder(xxx).append(yyy).append(zzz).toString(), + // convert it to STRING_CONCAT pseudo instruction. + if (callMth.getDeclClass().getFullName().equals(Consts.CLASS_STRING_BUILDER) + && callMth.getShortId().equals(Consts.MTH_TOSTRING_SIGNATURE) + && insn.getArg(0).isInsnWrap()) { + try { + List chain = flattenInsnChain(insn); + int constrIndex = -1; //RAF + // Case where new StringBuilder() is called with NO args (the entire + // string is created using .append() calls: + if (chain.size()>1 && chain.get(0).getType()==InsnType.CONSTRUCTOR) { + constrIndex = 0; + } else if (chain.size()>2 && chain.get(1).getType()==InsnType.CONSTRUCTOR) { + //RAF Case where the first string element is String arg to the + // new StringBuilder("xxx") constructor + constrIndex = 1; + } else if (chain.size()>3 && chain.get(2).getType()==InsnType.CONSTRUCTOR) { + //RAF Case where the first string element is String.valueOf() arg + // to the new StringBuilder(String.valueOf(zzz)) constructor + constrIndex = 2; + } + + if (constrIndex != -1) { // If we found a CONSTRUCTOR, is it a StringBuilder? + ConstructorInsn constr = (ConstructorInsn) chain.get(constrIndex); + if (constr.getClassType().getFullName().equals(Consts.CLASS_STRING_BUILDER)) { + int len = chain.size(), argInd = 1; + InsnNode concatInsn = new InsnNode(InsnType.STR_CONCAT, len-1); + InsnNode argInsn; + if (constrIndex > 0) { // There was an arg to the StringBuilder constr + InsnWrapArg iwa; + if (constrIndex==2 + && (argInsn = chain.get(1)).getType()==InsnType.INVOKE + && ((InvokeNode)argInsn).getCallMth().getName().compareTo("valueOf")==0) { + // The argument of new StringBuilder() is a String.valueOf(chainElement0) + iwa = (InsnWrapArg)argInsn.getArg(0); + argInd = 3; // Cause for loop below to skip to after the constructor + } else { + ConstStringNode csn = (ConstStringNode)chain.get(0); + iwa = new InsnWrapArg(csn); + argInd = 2; // Cause for loop below to skip to after the constructor + } + concatInsn.addArg(iwa); + } + + for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat + concatInsn.addArg(chain.get(argInd).getArg(1)); + } + concatInsn.setResult(insn.getResult()); + return concatInsn; + } // end of if constructor is for StringBuilder + } // end of if we found a constructor early in the chain + + } catch (Throwable e) { + LOG.debug("Can't convert string concatenation: {} insn: {}", mth, insn, e); + } + } + return null; } private static InsnNode simplifyArith(InsnNode insn) { -- GitLab