Projects STRLCPY jadx Commits 3782aa7d
🤬
  • core: fix wildcard type in iterable loop

  • Loading...
  • Skylot committed 9 years ago
    3782aa7d
    1 parent d5740c1b
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/regions/LoopRegionVisitor.java
    skipped 15 lines
    16 16  import jadx.core.dex.instructions.args.RegisterArg;
    17 17  import jadx.core.dex.instructions.args.SSAVar;
    18 18  import jadx.core.dex.nodes.BlockNode;
    19  -import jadx.core.dex.nodes.DexNode;
    20 19  import jadx.core.dex.nodes.IBlock;
    21 20  import jadx.core.dex.nodes.IRegion;
    22 21  import jadx.core.dex.nodes.InsnNode;
    skipped 209 lines
    232 231   }
    233 232   List<InsnNode> toSkip = new LinkedList<InsnNode>();
    234 233   RegisterArg iterVar = nextCall.getResult();
     234 + if (iterVar == null) {
     235 + return false;
     236 + }
    235 237   if (nextCall.contains(AFlag.WRAPPED)) {
    236 238   InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, nextCall);
    237 239   if (wrapArg != null && wrapArg.getParentInsn() != null) {
    238 240   InsnNode parentInsn = wrapArg.getParentInsn();
    239 241   if (parentInsn.getType() != InsnType.CHECK_CAST) {
     242 + if (!fixIterableType(mth, iterableArg, iterVar)) {
     243 + return false;
     244 + }
    240 245   parentInsn.replaceArg(wrapArg, iterVar);
    241 246   } else {
    242 247   iterVar = parentInsn.getResult();
     248 + if (iterVar == null || !fixIterableType(mth, iterableArg, iterVar)) {
     249 + return false;
     250 + }
    243 251   InsnArg castArg = BlockUtils.searchWrappedInsnParent(mth, parentInsn);
    244 252   if (castArg != null && castArg.getParentInsn() != null) {
    245 253   castArg.getParentInsn().replaceArg(castArg, iterVar);
    skipped 8 lines
    254 262   }
    255 263   } else {
    256 264   toSkip.add(nextCall);
    257  - }
    258  - if (iterVar == null || !fixIterableType(mth.dex(), iterableArg, iterVar)) {
    259  - return false;
    260 265   }
    261 266   
    262 267   assignInsn.add(AFlag.SKIP);
    skipped 4 lines
    267 272   return true;
    268 273   }
    269 274   
    270  - private static boolean fixIterableType(DexNode dex, InsnArg iterableArg, RegisterArg iterVar) {
     275 + private static boolean fixIterableType(MethodNode mth, InsnArg iterableArg, RegisterArg iterVar) {
    271 276   ArgType iterableType = iterableArg.getType();
    272 277   ArgType varType = iterVar.getType();
    273 278   if (iterableType.isGeneric()) {
    skipped 9 lines
    283 288   iterVar.setType(gType);
    284 289   return true;
    285 290   }
    286  - if (ArgType.isInstanceOf(dex, gType, varType)) {
     291 + if (ArgType.isInstanceOf(mth.dex(), gType, varType)) {
    287 292   return true;
    288 293   }
    289  - LOG.warn("Generic type differs: {} and {}", gType, varType);
     294 + ArgType wildcardType = gType.getWildcardType();
     295 + if (wildcardType != null
     296 + && gType.getWildcardBounds() == 1
     297 + && ArgType.isInstanceOf(mth.dex(), wildcardType, varType)) {
     298 + return true;
     299 + }
     300 + LOG.warn("Generic type differs: '{}' and '{}' in {}", gType, varType, mth);
    290 301   return false;
    291 302   }
    292 303   if (!iterableArg.isRegister()) {
    skipped 75 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/integration/generics/TestGenerics6.java
     1 +package jadx.tests.integration.generics;
     2 + 
     3 +import jadx.core.dex.nodes.ClassNode;
     4 +import jadx.tests.api.IntegrationTest;
     5 + 
     6 +import java.util.Collection;
     7 + 
     8 +import org.junit.Test;
     9 + 
     10 +import static jadx.tests.api.utils.JadxMatchers.containsOne;
     11 +import static org.junit.Assert.assertThat;
     12 + 
     13 +public class TestGenerics6 extends IntegrationTest {
     14 + 
     15 + public static class TestCls {
     16 + public void test1(Collection<? extends A> as) {
     17 + for (A a : as) {
     18 + a.f();
     19 + }
     20 + }
     21 + 
     22 + public void test2(Collection<? extends A> is) {
     23 + for (I i : is) {
     24 + i.f();
     25 + }
     26 + }
     27 + 
     28 + private interface I {
     29 + void f();
     30 + }
     31 + 
     32 + private class A implements I {
     33 + public void f() {
     34 + }
     35 + }
     36 + }
     37 + 
     38 + @Test
     39 + public void test() {
     40 + ClassNode cls = getClassNode(TestCls.class);
     41 + String code = cls.getCode().toString();
     42 + 
     43 + assertThat(code, containsOne("for (A a : as) {"));
     44 + // TODO: fix iterable arg type (unexpected cast to A in bytecode)
     45 +// assertThat(code, containsOne("for (I i : is) {"));
     46 + }
     47 +}
     48 + 
Please wait...
Page is in error, reload to recover