Skip to content

Commit

Permalink
fix: incorrect init values of inherited fields
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jul 13, 2019
1 parent 49e234d commit ed9fe8a
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 3 deletions.
Expand Up @@ -92,7 +92,7 @@ private static void moveStaticFieldsInit(ClassNode cls) {
List<InsnNode> initInsns = getFieldAssigns(classInitMth, field, InsnType.SPUT);
if (initInsns.size() == 1) {
InsnNode insn = initInsns.get(0);
if (checkInsn(insn)) {
if (checkInsn(cls, insn)) {
InsnArg arg = insn.getArg(0);
if (arg instanceof InsnWrapArg) {
((InsnWrapArg) arg).getWrapInsn().add(AFlag.DECLARE_VAR);
Expand Down Expand Up @@ -137,7 +137,7 @@ private static void moveCommonFieldsInit(ClassNode cls) {
// TODO: check not only first block
BlockNode blockNode = constrMth.getBasicBlocks().get(0);
for (InsnNode insn : blockNode.getInstructions()) {
if (insn.getType() == InsnType.IPUT && checkInsn(insn)) {
if (insn.getType() == InsnType.IPUT && checkInsn(cls, insn)) {
info.getPutInsns().add(insn);
} else if (!info.getPutInsns().isEmpty()) {
break;
Expand Down Expand Up @@ -199,7 +199,22 @@ private static boolean compareInsns(List<InsnNode> base, List<InsnNode> other) {
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);
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
Expand Down
@@ -0,0 +1,57 @@
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;"));
}
}

0 comments on commit ed9fe8a

Please sign in to comment.