Commit ed9fe8a5 authored by Skylot's avatar Skylot

fix: incorrect init values of inherited fields

parent 49e234d9
...@@ -92,7 +92,7 @@ public class ExtractFieldInit extends AbstractVisitor { ...@@ -92,7 +92,7 @@ public class ExtractFieldInit extends AbstractVisitor {
List<InsnNode> initInsns = getFieldAssigns(classInitMth, field, InsnType.SPUT); List<InsnNode> initInsns = getFieldAssigns(classInitMth, field, InsnType.SPUT);
if (initInsns.size() == 1) { if (initInsns.size() == 1) {
InsnNode insn = initInsns.get(0); InsnNode insn = initInsns.get(0);
if (checkInsn(insn)) { if (checkInsn(cls, insn)) {
InsnArg arg = insn.getArg(0); InsnArg arg = insn.getArg(0);
if (arg instanceof InsnWrapArg) { if (arg instanceof InsnWrapArg) {
((InsnWrapArg) arg).getWrapInsn().add(AFlag.DECLARE_VAR); ((InsnWrapArg) arg).getWrapInsn().add(AFlag.DECLARE_VAR);
...@@ -137,7 +137,7 @@ public class ExtractFieldInit extends AbstractVisitor { ...@@ -137,7 +137,7 @@ public class ExtractFieldInit extends AbstractVisitor {
// TODO: check not only first block // TODO: check not only first block
BlockNode blockNode = constrMth.getBasicBlocks().get(0); BlockNode blockNode = constrMth.getBasicBlocks().get(0);
for (InsnNode insn : blockNode.getInstructions()) { for (InsnNode insn : blockNode.getInstructions()) {
if (insn.getType() == InsnType.IPUT && checkInsn(insn)) { if (insn.getType() == InsnType.IPUT && checkInsn(cls, insn)) {
info.getPutInsns().add(insn); info.getPutInsns().add(insn);
} else if (!info.getPutInsns().isEmpty()) { } else if (!info.getPutInsns().isEmpty()) {
break; break;
...@@ -199,7 +199,22 @@ public class ExtractFieldInit extends AbstractVisitor { ...@@ -199,7 +199,22 @@ public class ExtractFieldInit extends AbstractVisitor {
return true; return true;
} }
private static boolean checkInsn(InsnNode insn) { private static boolean checkInsn(ClassNode cls, InsnNode insn) {
if (insn instanceof IndexInsnNode) {
FieldInfo fieldInfo = (FieldInfo) ((IndexInsnNode) insn).getIndex();
if (!fieldInfo.getDeclClass().equals(cls.getClassInfo())) {
// exclude fields from super classes
return false;
}
FieldNode fieldNode = cls.dex().resolveField(fieldInfo);
if (fieldNode == null) {
// exclude inherited fields (not declared in this class)
return false;
}
} else {
return false;
}
InsnArg arg = insn.getArg(0); InsnArg arg = insn.getArg(0);
if (arg.isInsnWrap()) { if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn(); InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
......
package jadx.tests.integration.others;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class TestFieldInit3 extends IntegrationTest {
public static class TestCls {
public abstract static class A {
public int field = 4;
}
public static final class B extends A {
public B() {
// IPUT for A.field
super.field = 7;
}
}
public static final class C extends A {
public int other = 11;
public C() {
// IPUT for C.field not A.field !!!
this.field = 9;
}
}
public static final class D extends A {
}
public void check() {
assertThat(new B().field, is(7));
assertThat(new C().field, is(9));
assertThat(new C().other, is(11));
assertThat(new D().field, is(4));
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("public int field = 4;"));
assertThat(code, containsOne("field = 7;"));
assertThat(code, containsOne("field = 9;"));
assertThat(code, containsOne("public int other = 11;"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment