From e4dde3f4b602874096c478ed1ce227d93fe0cef4 Mon Sep 17 00:00:00 2001 From: Skylot Date: Sun, 15 Jun 2014 21:35:34 +0400 Subject: [PATCH] core: fix class cast exception --- .../main/java/jadx/api/JadxDecompiler.java | 2 +- .../main/java/jadx/core/codegen/InsnGen.java | 2 +- .../core/dex/instructions/args/FieldArg.java | 18 ++++----- .../core/dex/visitors/SimplifyVisitor.java | 5 +-- .../jadx/core/utils/InstructionRemover.java | 22 ++++++---- .../{ => arith}/TestFieldIncrement.java | 2 +- .../internal/arith/TestFieldIncrement2.java | 40 +++++++++++++++++++ 7 files changed, 69 insertions(+), 22 deletions(-) rename jadx-core/src/test/java/jadx/tests/internal/{ => arith}/TestFieldIncrement.java (96%) create mode 100644 jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement2.java diff --git a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java index 3bac9c19..49a1e8b9 100644 --- a/jadx-core/src/main/java/jadx/api/JadxDecompiler.java +++ b/jadx-core/src/main/java/jadx/api/JadxDecompiler.java @@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory; /** * Jadx API usage example: *

- *  Decompiler jadx = new Decompiler();
+ *  JadxDecompiler jadx = new JadxDecompiler();
  *  jadx.loadFile(new File("classes.dex"));
  *  jadx.setOutputDir(new File("out"));
  *  jadx.save();
diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
index 87e991cd..fc7460e5 100644
--- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
@@ -101,7 +101,7 @@ public class InsnGen {
 			if (f.isStatic()) {
 				staticField(code, f.getField());
 			} else {
-				instanceField(code, f.getField(), f.getRegisterArg());
+				instanceField(code, f.getField(), f.getInstanceArg());
 			}
 		} else {
 			throw new CodegenException("Unknown arg type " + arg);
diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java
index 3ca5a099..6e001078 100644
--- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java
+++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/FieldArg.java
@@ -6,12 +6,12 @@ import jadx.core.dex.info.FieldInfo;
 public final class FieldArg extends RegisterArg {
 
 	private final FieldInfo field;
-	// regArg equal 'null' for static fields
-	private final RegisterArg regArg;
+	// instArg equal 'null' for static fields
+	private final InsnArg instArg;
 
-	public FieldArg(FieldInfo field, RegisterArg reg) {
+	public FieldArg(FieldInfo field, InsnArg reg) {
 		super(-1);
-		this.regArg = reg;
+		this.instArg = reg;
 		this.field = field;
 	}
 
@@ -19,12 +19,12 @@ public final class FieldArg extends RegisterArg {
 		return field;
 	}
 
-	public RegisterArg getRegisterArg() {
-		return regArg;
+	public InsnArg getInstanceArg() {
+		return instArg;
 	}
 
 	public boolean isStatic() {
-		return regArg == null;
+		return instArg == null;
 	}
 
 	@Override
@@ -54,7 +54,7 @@ public final class FieldArg extends RegisterArg {
 		if (!field.equals(fieldArg.field)) {
 			return false;
 		}
-		if (regArg != null ? !regArg.equals(fieldArg.regArg) : fieldArg.regArg != null) {
+		if (instArg != null ? !instArg.equals(fieldArg.instArg) : fieldArg.instArg != null) {
 			return false;
 		}
 		return true;
@@ -64,7 +64,7 @@ public final class FieldArg extends RegisterArg {
 	public int hashCode() {
 		int result = super.hashCode();
 		result = 31 * result + field.hashCode();
-		result = 31 * result + (regArg != null ? regArg.hashCode() : 0);
+		result = 31 * result + (instArg != null ? instArg.hashCode() : 0);
 		return result;
 	}
 
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 a4e0b824..924a7e03 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
@@ -14,7 +14,6 @@ import jadx.core.dex.instructions.args.FieldArg;
 import jadx.core.dex.instructions.args.InsnArg;
 import jadx.core.dex.instructions.args.InsnWrapArg;
 import jadx.core.dex.instructions.args.LiteralArg;
-import jadx.core.dex.instructions.args.RegisterArg;
 import jadx.core.dex.instructions.mods.ConstructorInsn;
 import jadx.core.dex.nodes.BlockNode;
 import jadx.core.dex.nodes.InsnNode;
@@ -186,9 +185,9 @@ public class SimplifyVisitor extends AbstractVisitor {
 			return null;
 		}
 		try {
-			RegisterArg reg = null;
+			InsnArg reg = null;
 			if (getType == InsnType.IGET) {
-				reg = ((RegisterArg) get.getArg(0));
+				reg = get.getArg(0);
 			}
 			FieldArg fArg = new FieldArg(field, reg);
 			if (reg != null) {
diff --git a/jadx-core/src/main/java/jadx/core/utils/InstructionRemover.java b/jadx-core/src/main/java/jadx/core/utils/InstructionRemover.java
index 39bc385c..f0a781e3 100644
--- a/jadx-core/src/main/java/jadx/core/utils/InstructionRemover.java
+++ b/jadx-core/src/main/java/jadx/core/utils/InstructionRemover.java
@@ -3,6 +3,7 @@ package jadx.core.utils;
 import jadx.core.Consts;
 import jadx.core.dex.attributes.AFlag;
 import jadx.core.dex.instructions.args.InsnArg;
+import jadx.core.dex.instructions.args.InsnWrapArg;
 import jadx.core.dex.instructions.args.RegisterArg;
 import jadx.core.dex.instructions.args.SSAVar;
 import jadx.core.dex.nodes.BlockNode;
@@ -65,17 +66,24 @@ public class InstructionRemover {
 			mth.removeSVar(r.getSVar());
 		}
 		for (InsnArg arg : insn.getArguments()) {
-			if (arg instanceof RegisterArg) {
-				RegisterArg reg = (RegisterArg) arg;
-				SSAVar sVar = reg.getSVar();
-				if (sVar != null) {
-					sVar.removeUse(reg);
-				}
-			}
+			unbindArgUsage(mth, arg);
 		}
 		insn.add(AFlag.INCONSISTENT_CODE);
 	}
 
+	public static void unbindArgUsage(MethodNode mth, InsnArg arg) {
+		if (arg instanceof RegisterArg) {
+			RegisterArg reg = (RegisterArg) arg;
+			SSAVar sVar = reg.getSVar();
+			if (sVar != null) {
+				sVar.removeUse(reg);
+			}
+		} else if (arg instanceof InsnWrapArg) {
+			InsnWrapArg wrap = (InsnWrapArg) arg;
+			unbindInsn(mth, wrap.getWrapInsn());
+		}
+	}
+
 	// Don't use 'insns.removeAll(toRemove)' because it will remove instructions by content
 	// and here can be several instructions with same content
 	private void removeAll(List insns, List toRemove) {
diff --git a/jadx-core/src/test/java/jadx/tests/internal/TestFieldIncrement.java b/jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement.java
similarity index 96%
rename from jadx-core/src/test/java/jadx/tests/internal/TestFieldIncrement.java
rename to jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement.java
index b4806970..51192fee 100644
--- a/jadx-core/src/test/java/jadx/tests/internal/TestFieldIncrement.java
+++ b/jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement.java
@@ -1,4 +1,4 @@
-package jadx.tests.internal;
+package jadx.tests.internal.arith;
 
 import jadx.api.InternalJadxTest;
 import jadx.core.dex.nodes.ClassNode;
diff --git a/jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement2.java b/jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement2.java
new file mode 100644
index 00000000..b1aa72bc
--- /dev/null
+++ b/jadx-core/src/test/java/jadx/tests/internal/arith/TestFieldIncrement2.java
@@ -0,0 +1,40 @@
+package jadx.tests.internal.arith;
+
+import jadx.api.InternalJadxTest;
+import jadx.core.dex.nodes.ClassNode;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+public class TestFieldIncrement2 extends InternalJadxTest {
+
+	class A {
+		int f = 5;
+	}
+
+	public static class TestCls {
+		public A a;
+
+		public void test1(int n) {
+			this.a.f = this.a.f + n;
+		}
+
+		public void test2(int n) {
+			this.a.f *= n;
+		}
+	}
+
+	@Test
+	public void test() {
+		ClassNode cls = getClassNode(TestCls.class);
+		String code = cls.getCode().toString();
+		System.out.println(code);
+
+		assertThat(code, containsString("this.a.f += n;"));
+		assertThat(code, containsString("a.f *= n;"));
+		// TODO
+		// assertThat(code, containsString("this.a.f *= n;"));
+	}
+}
-- 
GitLab