core: check arguments for field arithmetic operations (fix #40)
This commit is contained in:
@@ -2,14 +2,17 @@ package jadx.core.dex.instructions.args;
|
||||
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
// TODO: don't extend RegisterArg (now used as a result of instruction)
|
||||
public final class FieldArg extends RegisterArg {
|
||||
|
||||
private final FieldInfo field;
|
||||
// instArg equal 'null' for static fields
|
||||
@Nullable
|
||||
private final InsnArg instArg;
|
||||
|
||||
public FieldArg(FieldInfo field, InsnArg reg) {
|
||||
public FieldArg(FieldInfo field, @Nullable InsnArg reg) {
|
||||
super(-1);
|
||||
this.instArg = reg;
|
||||
this.field = field;
|
||||
|
||||
@@ -2,11 +2,13 @@ package jadx.core.dex.instructions.args;
|
||||
|
||||
import jadx.core.dex.nodes.InsnNode;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class InsnWrapArg extends InsnArg {
|
||||
|
||||
private final InsnNode wrappedInsn;
|
||||
|
||||
public InsnWrapArg(InsnNode insn) {
|
||||
public InsnWrapArg(@NotNull InsnNode insn) {
|
||||
RegisterArg result = insn.getResult();
|
||||
this.type = result != null ? result.getType() : ArgType.VOID;
|
||||
this.wrappedInsn = insn;
|
||||
@@ -27,6 +29,34 @@ public final class InsnWrapArg extends InsnArg {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return wrappedInsn.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof InsnWrapArg)) {
|
||||
return false;
|
||||
}
|
||||
InsnWrapArg that = (InsnWrapArg) o;
|
||||
InsnNode thisInsn = wrappedInsn;
|
||||
InsnNode thatInsn = that.wrappedInsn;
|
||||
if (!thisInsn.isSame(thatInsn)) {
|
||||
return false;
|
||||
}
|
||||
int count = thisInsn.getArgsCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!thisInsn.getArg(i).equals(thatInsn.getArg(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(wrap: " + type + "\n " + wrappedInsn + ")";
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package jadx.core.dex.instructions.args;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class NamedArg extends InsnArg implements Named {
|
||||
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
public NamedArg(String name, ArgType type) {
|
||||
public NamedArg(@NotNull String name, @NotNull ArgType type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -18,10 +22,27 @@ public final class NamedArg extends InsnArg implements Named {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
public void setName(@NotNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof NamedArg)) {
|
||||
return false;
|
||||
}
|
||||
return name.equals(((NamedArg) o).name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(" + name + " " + type + ")";
|
||||
|
||||
@@ -55,8 +55,7 @@ public class TypeImmutableArg extends RegisterArg {
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
TypeImmutableArg that = (TypeImmutableArg) obj;
|
||||
return isThis == that.isThis;
|
||||
return isThis == ((TypeImmutableArg) obj).isThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -137,7 +137,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
private static InsnNode convertInvoke(MethodNode mth, InsnNode insn) {
|
||||
MethodInfo callMth = ((InvokeNode) insn).getCallMth();
|
||||
|
||||
// If this is a 'new StringBuilder(xxx).append(yyy).append(zzz).toString(),
|
||||
// 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)
|
||||
@@ -150,11 +150,11 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
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
|
||||
//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
|
||||
//RAF Case where the first string element is String.valueOf() arg
|
||||
// to the new StringBuilder(String.valueOf(zzz)) constructor
|
||||
constrIndex = 2;
|
||||
}
|
||||
@@ -167,7 +167,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
InsnNode argInsn;
|
||||
if (constrIndex > 0) { // There was an arg to the StringBuilder constr
|
||||
InsnWrapArg iwa;
|
||||
if (constrIndex==2
|
||||
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)
|
||||
@@ -181,7 +181,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
concatInsn.addArg(iwa);
|
||||
}
|
||||
|
||||
for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat
|
||||
for (; argInd < len; argInd++) { // Add the .append(xxx) arg string to concat
|
||||
concatInsn.addArg(chain.get(argInd).getArg(1));
|
||||
}
|
||||
concatInsn.setResult(insn.getResult());
|
||||
@@ -252,6 +252,10 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
InsnArg reg = null;
|
||||
if (getType == InsnType.IGET) {
|
||||
reg = get.getArg(0);
|
||||
InsnArg putReg = insn.getArg(1);
|
||||
if (!reg.equals(putReg)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
FieldArg fArg = new FieldArg(field, reg);
|
||||
if (reg != null) {
|
||||
@@ -268,7 +272,7 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
}
|
||||
return new ArithNode(ArithOp.ADD, fArg, InsnArg.wrapArg(concat));
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
} catch (Exception e) {
|
||||
LOG.debug("Can't convert field arith insn: {}, mth: {}", insn, mth, e);
|
||||
}
|
||||
return null;
|
||||
@@ -289,4 +293,4 @@ public class SimplifyVisitor extends AbstractVisitor {
|
||||
Collections.reverse(chain);
|
||||
return chain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package jadx.tests.integration.arith;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class TestFieldIncrement3 extends IntegrationTest {
|
||||
|
||||
public static class TestCls {
|
||||
static int tileX;
|
||||
static int tileY;
|
||||
static Vector2 targetPos = new Vector2();
|
||||
static Vector2 directVect = new Vector2();
|
||||
static Vector2 newPos = new Vector2();
|
||||
|
||||
private static void test() {
|
||||
Random rd = new Random();
|
||||
int direction = rd.nextInt(7);
|
||||
switch (direction) {
|
||||
case 0:
|
||||
targetPos.x = (float) (((tileX + 1) * 55) + 55);
|
||||
targetPos.y = (float) (((tileY + 1) * 35) + 35);
|
||||
break;
|
||||
case 2:
|
||||
targetPos.x = (float) (((tileX + 1) * 55) + 55);
|
||||
targetPos.y = (float) (((tileY - 1) * 35) + 35);
|
||||
break;
|
||||
case 4:
|
||||
targetPos.x = (float) (((tileX - 1) * 55) + 55);
|
||||
targetPos.y = (float) (((tileY - 1) * 35) + 35);
|
||||
break;
|
||||
case 6:
|
||||
targetPos.x = (float) (((tileX - 1) * 55) + 55);
|
||||
targetPos.y = (float) (((tileY + 1) * 35) + 35);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
directVect.x = targetPos.x - newPos.x;
|
||||
directVect.y = targetPos.y - newPos.y;
|
||||
|
||||
float hPos = (float) Math.sqrt((double) ((directVect.x * directVect.x) + (directVect.y * directVect.y)));
|
||||
directVect.x /= hPos;
|
||||
directVect.y /= hPos;
|
||||
}
|
||||
|
||||
static class Vector2 {
|
||||
public float x;
|
||||
public float y;
|
||||
|
||||
public Vector2() {
|
||||
this.x = 0.0f;
|
||||
this.y = 0.0f;
|
||||
}
|
||||
|
||||
public boolean equals(Vector2 other) {
|
||||
return (this.x == other.x && this.y == other.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsString("directVect.x = targetPos.x - newPos.x;"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user