提交 ae31fee8 编写于 作者: S Skylot

fix: add cast to exact type on field access (#729)

上级 e7b00cc7
......@@ -41,10 +41,15 @@ public class IndexInsnNode extends InsnNode {
switch (insnType) {
case CAST:
case CHECK_CAST:
return InsnUtils.formatOffset(offset) + ": "
+ InsnUtils.insnTypeToString(insnType)
+ getResult() + " = (" + InsnUtils.indexToString(index) + ") "
+ Utils.listToString(getArguments());
StringBuilder sb = new StringBuilder();
sb.append(InsnUtils.formatOffset(offset)).append(": ");
sb.append(insnType).append(' ');
if (getResult() != null) {
sb.append(getResult()).append(" = ");
}
sb.append('(').append(InsnUtils.indexToString(index)).append(") ");
sb.append(Utils.listToString(getArguments()));
return sb.toString();
default:
return super.toString() + ' ' + InsnUtils.indexToString(index);
......
......@@ -30,6 +30,7 @@ import jadx.core.dex.nodes.utils.MethodUtils;
import jadx.core.dex.nodes.utils.TypeUtils;
import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.dex.visitors.typeinference.TypeCompare;
import jadx.core.dex.visitors.typeinference.TypeUpdate;
import jadx.core.utils.CacheStorage;
import jadx.core.utils.ErrorsCounter;
......@@ -424,6 +425,10 @@ public class RootNode {
return typeUpdate;
}
public TypeCompare getTypeCompare() {
return typeUpdate.getTypeCompare();
}
public ICodeCache getCodeCache() {
return codeCache;
}
......
......@@ -33,6 +33,7 @@ import jadx.core.dex.instructions.NewArrayNode;
import jadx.core.dex.instructions.SwitchInsn;
import jadx.core.dex.instructions.args.ArgType;
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.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
......@@ -49,6 +50,7 @@ import jadx.core.dex.trycatch.ExcHandlerAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.visitors.regions.variables.ProcessVariables;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.dex.visitors.typeinference.TypeCompareEnum;
import jadx.core.utils.InsnRemover;
import jadx.core.utils.InsnUtils;
import jadx.core.utils.exceptions.JadxException;
......@@ -144,6 +146,11 @@ public class ModVisitor extends AbstractVisitor {
fixPrimitiveCast(mth, block, i, insn);
break;
case IPUT:
case IGET:
fixTypeForFieldAccess(mth, (IndexInsnNode) insn);
break;
default:
break;
}
......@@ -152,6 +159,31 @@ public class ModVisitor extends AbstractVisitor {
}
}
private static void fixTypeForFieldAccess(MethodNode mth, IndexInsnNode insn) {
InsnArg instanceArg = insn.getArg(insn.getType() == InsnType.IGET ? 0 : 1);
if (instanceArg.contains(AFlag.SUPER)) {
return;
}
if (instanceArg.isInsnWrap() && ((InsnWrapArg) instanceArg).getWrapInsn().getType() == InsnType.CAST) {
return;
}
FieldInfo fieldInfo = (FieldInfo) insn.getIndex();
ArgType clsType = fieldInfo.getDeclClass().getType();
ArgType instanceType = instanceArg.getType();
TypeCompareEnum result = mth.root().getTypeCompare().compareTypes(instanceType, clsType);
if (result.isEqual() || (result == TypeCompareEnum.NARROW_BY_GENERIC && !instanceType.isGenericType())) {
return;
}
IndexInsnNode castInsn = new IndexInsnNode(InsnType.CAST, clsType, 1);
castInsn.addArg(instanceArg.duplicate());
castInsn.add(AFlag.EXPLICIT_CAST);
InsnArg castArg = InsnArg.wrapInsnIntoArg(castInsn);
castArg.setType(clsType);
insn.replaceArg(instanceArg, castArg);
InsnRemover.unbindArgUsage(mth, instanceArg);
}
private static void replaceConstKeys(ClassNode parentClass, SwitchInsn insn) {
int[] keys = insn.getKeys();
int len = keys.length;
......
package jadx.tests.integration.types;
import org.junit.jupiter.api.Test;
import jadx.tests.api.IntegrationTest;
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
public class TestFieldAccess extends IntegrationTest {
public static class TestCls {
private String field;
static <T extends TestCls> T testPut(T t) {
((TestCls) t).field = "";
return t;
}
static <T extends TestCls> T testGet(T t) {
System.out.println(((TestCls) t).field);
return t;
}
}
@Test
public void test() {
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("t.field");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册