This commit is contained in:
@@ -33,6 +33,21 @@ public final class MethodInfo {
|
||||
shortId = makeSignature(true);
|
||||
}
|
||||
|
||||
private MethodInfo(ClassInfo declClass, String name, List<ArgType> args, ArgType retType) {
|
||||
this.name = name;
|
||||
alias = name;
|
||||
aliasFromPreset = false;
|
||||
this.declClass = declClass;
|
||||
|
||||
this.args = args;
|
||||
this.retType = retType;
|
||||
shortId = makeSignature(true);
|
||||
}
|
||||
|
||||
public static MethodInfo externalMth(ClassInfo declClass, String name, List<ArgType> args, ArgType retType) {
|
||||
return new MethodInfo(declClass, name, args, retType);
|
||||
}
|
||||
|
||||
public static MethodInfo fromDex(DexNode dex, int mthIndex) {
|
||||
MethodInfo mth = dex.root().getInfoStorage().getMethod(dex, mthIndex);
|
||||
if (mth != null) {
|
||||
|
||||
@@ -36,7 +36,7 @@ public class InvokeNode extends InsnNode implements CallMthInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private InvokeNode(MethodInfo mth, InvokeType invokeType, int argsCount) {
|
||||
public InvokeNode(MethodInfo mth, InvokeType invokeType, int argsCount) {
|
||||
super(InsnType.INVOKE, argsCount);
|
||||
this.mth = mth;
|
||||
this.type = invokeType;
|
||||
|
||||
@@ -8,7 +8,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import jadx.core.Consts;
|
||||
import jadx.core.deobf.NameMapper;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
import jadx.core.dex.info.MethodInfo;
|
||||
import jadx.core.dex.instructions.ArithNode;
|
||||
@@ -19,6 +21,7 @@ import jadx.core.dex.instructions.IfNode;
|
||||
import jadx.core.dex.instructions.IndexInsnNode;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
import jadx.core.dex.instructions.InvokeNode;
|
||||
import jadx.core.dex.instructions.InvokeType;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.FieldArg;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
@@ -29,6 +32,7 @@ import jadx.core.dex.instructions.mods.TernaryInsn;
|
||||
import jadx.core.dex.nodes.BlockNode;
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
import jadx.core.dex.nodes.MethodNode;
|
||||
import jadx.core.dex.nodes.RootNode;
|
||||
import jadx.core.dex.regions.conditions.IfCondition;
|
||||
|
||||
public class SimplifyVisitor extends AbstractVisitor {
|
||||
@@ -95,12 +99,55 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
}
|
||||
break;
|
||||
|
||||
case CONSTRUCTOR:
|
||||
simplfyConstructor(mth.root(), (ConstructorInsn) insn);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void simplfyConstructor(RootNode root, ConstructorInsn insn) {
|
||||
if (insn.getArgsCount() != 0
|
||||
&& insn.getCallMth().getDeclClass().getType().equals(ArgType.STRING)) {
|
||||
InsnArg arg = insn.getArg(0);
|
||||
InsnNode node = arg.isInsnWrap()
|
||||
? ((InsnWrapArg) arg).getWrapInsn()
|
||||
: insn;
|
||||
if (node.getArgsCount() != 0) {
|
||||
ArgType argType = node.getArg(0).getType();
|
||||
if (node.getType() == InsnType.FILLED_NEW_ARRAY
|
||||
&& (argType == ArgType.BYTE || argType == ArgType.CHAR)) {
|
||||
int printable = 0;
|
||||
byte[] arr = new byte[node.getArgsCount()];
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
arr[i] = (byte) ((LiteralArg) node.getArg(i)).getLiteral();
|
||||
if (NameMapper.isPrintableChar(arr[i])) {
|
||||
printable++;
|
||||
}
|
||||
}
|
||||
if (printable >= arr.length - printable) {
|
||||
InsnWrapArg wa = new InsnWrapArg(new ConstStringNode(new String(arr)));
|
||||
if (insn.getArgsCount() == 1) {
|
||||
insn.setArg(0, wa);
|
||||
} else {
|
||||
MethodInfo mi = MethodInfo.externalMth(
|
||||
ClassInfo.fromType(root, ArgType.STRING),
|
||||
"getBytes",
|
||||
Collections.emptyList(),
|
||||
ArgType.array(ArgType.BYTE));
|
||||
InvokeNode in = new InvokeNode(mi, InvokeType.VIRTUAL, 1);
|
||||
in.addArg(wa);
|
||||
insn.setArg(0, new InsnWrapArg(in));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static InsnNode processCast(MethodNode mth, InsnNode insn) {
|
||||
InsnArg castArg = insn.getArg(0);
|
||||
ArgType argType = castArg.getType();
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package jadx.tests.integration.others;
|
||||
|
||||
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
public class TestStringConstructor extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
public String tag = new String(new byte[] {'a', 'b', 'c'});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("abc"));
|
||||
}
|
||||
|
||||
public static class TestCls2 {
|
||||
public String tag = new String(new byte[] {'a', 'b', 'c'}, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
ClassNode cls = getClassNode(TestCls2.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("new String(\"abc\".getBytes(), StandardCharsets.UTF_8)"));
|
||||
}
|
||||
|
||||
public static class TestCls3 {
|
||||
public String tag = new String(new byte[] {1, 2, 3, 'a', 'b', 'c'});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test3() {
|
||||
ClassNode cls = getClassNode(TestCls3.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("\\u0001\\u0002\\u0003abc"));
|
||||
}
|
||||
|
||||
public static class TestCls4 {
|
||||
public String tag = new String(new char[] {1, 2, 3, 'a', 'b', 'c'});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
ClassNode cls = getClassNode(TestCls4.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("\\u0001\\u0002\\u0003abc"));
|
||||
}
|
||||
|
||||
public static class TestCls5 {
|
||||
public String tag = new String(new char[] {1, 2, 3, 'a', 'b'});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test5() {
|
||||
ClassNode cls = getClassNode(TestCls5.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("{1, 2, 3, 'a', 'b'}"));
|
||||
}
|
||||
|
||||
public static class TestClsNegative {
|
||||
public String tag = new String();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNegative() {
|
||||
ClassNode cls = getClassNode(TestClsNegative.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsOne("tag = new String();"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user