Projects STRLCPY jadx Commits b66293a2
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java
    skipped 191 lines
    192 192   return usedInPhi;
    193 193   }
    194 194   
     195 + public boolean isAssignInPhi() {
     196 + InsnNode assignInsn = getAssignInsn();
     197 + return assignInsn != null && assignInsn.getType() == InsnType.PHI;
     198 + }
     199 + 
    195 200   public boolean isUsedInPhi() {
    196 201   return usedInPhi != null && !usedInPhi.isEmpty();
    197 202   }
    skipped 119 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/MoveInlineVisitor.java
    skipped 51 lines
    52 52   if (resultArg.sameRegAndSVar(moveArg)) {
    53 53   return true;
    54 54   }
     55 + if (moveArg.isRegister()) {
     56 + RegisterArg moveReg = (RegisterArg) moveArg;
     57 + if (moveReg.getSVar().isAssignInPhi()) {
     58 + // don't mix already merged variables
     59 + return false;
     60 + }
     61 + }
    55 62   SSAVar ssaVar = resultArg.getSVar();
    56 63   if (ssaVar.isUsedInPhi()) {
    57 64   return deleteMove(mth, move);
    skipped 71 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeBoundCheckCastAssign.java
    skipped 45 lines
    46 46   return insn.getResult();
    47 47   }
    48 48   
     49 + public IndexInsnNode getInsn() {
     50 + return insn;
     51 + }
     52 + 
    49 53   @Override
    50 54   public String toString() {
    51 55   return "CHECK_CAST_ASSIGN{(" + insn.getIndex() + ") " + insn.getArg(0).getType() + "}";
    skipped 3 lines
  • ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeBoundInvokeAssign.java
    1 1  package jadx.core.dex.visitors.typeinference;
    2 2   
     3 +import org.jetbrains.annotations.Nullable;
     4 + 
    3 5  import jadx.core.dex.instructions.InvokeNode;
    4 6  import jadx.core.dex.instructions.args.ArgType;
    5 7  import jadx.core.dex.instructions.args.InsnArg;
    skipped 42 lines
    48 50   mthDeclType = instanceType;
    49 51   }
    50 52   ArgType resultGeneric = root.getTypeUtils().replaceClassGenerics(instanceType, mthDeclType, genericReturnType);
    51  - if (resultGeneric != null && !resultGeneric.isWildcard()) {
    52  - return resultGeneric;
     53 + ArgType result = processResultType(resultGeneric);
     54 + if (result != null) {
     55 + return result;
    53 56   }
    54 57   return invokeNode.getCallMth().getReturnType();
     58 + }
     59 + 
     60 + @Nullable
     61 + private ArgType processResultType(@Nullable ArgType resultGeneric) {
     62 + if (resultGeneric == null) {
     63 + return null;
     64 + }
     65 + if (!resultGeneric.isWildcard()) {
     66 + return resultGeneric;
     67 + }
     68 + return resultGeneric.getWildcardType();
    55 69   }
    56 70   
    57 71   private InsnArg getInstanceArg() {
    skipped 35 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java
    skipped 56 lines
    57 57  import jadx.core.utils.BlockUtils;
    58 58  import jadx.core.utils.InsnList;
    59 59  import jadx.core.utils.InsnUtils;
     60 +import jadx.core.utils.ListUtils;
    60 61  import jadx.core.utils.Utils;
    61 62  import jadx.core.utils.exceptions.JadxOverflowException;
    62 63   
    skipped 20 lines
    83 84   this.resolvers = Arrays.asList(
    84 85   this::initTypeBounds,
    85 86   this::runTypePropagation,
     87 + this::tryRestoreTypeVarCasts,
    86 88   this::tryInsertCasts,
    87 89   this::tryDeduceTypes,
    88 90   this::trySplitConstInsns,
    skipped 431 lines
    520 522   return false;
    521 523   }
    522 524   
    523  - @SuppressWarnings("ForLoopReplaceableByWhile")
     525 + /**
     526 + * Fix check casts to type var extend type:
     527 + * <br>
     528 + * {@code <T extends Comparable> T var = (Comparable) obj; => T var = (T) obj; }
     529 + */
     530 + private boolean tryRestoreTypeVarCasts(MethodNode mth) {
     531 + int changed = 0;
     532 + List<SSAVar> mthSVars = mth.getSVars();
     533 + for (SSAVar var : mthSVars) {
     534 + changed += restoreTypeVarCasts(var);
     535 + }
     536 + if (changed == 0) {
     537 + return false;
     538 + }
     539 + if (Consts.DEBUG_TYPE_INFERENCE) {
     540 + mth.addDebugComment("Restore " + changed + " type vars casts");
     541 + }
     542 + initTypeBounds(mth);
     543 + return runTypePropagation(mth);
     544 + }
     545 + 
     546 + private int restoreTypeVarCasts(SSAVar var) {
     547 + TypeInfo typeInfo = var.getTypeInfo();
     548 + Set<ITypeBound> bounds = typeInfo.getBounds();
     549 + if (!ListUtils.anyMatch(bounds, t -> t.getType().isGenericType())) {
     550 + return 0;
     551 + }
     552 + List<ITypeBound> casts = ListUtils.filter(bounds, TypeBoundCheckCastAssign.class::isInstance);
     553 + if (casts.isEmpty()) {
     554 + return 0;
     555 + }
     556 + ArgType bestType = selectBestTypeFromBounds(bounds).orElse(ArgType.UNKNOWN);
     557 + if (!bestType.isGenericType()) {
     558 + return 0;
     559 + }
     560 + List<ArgType> extendTypes = bestType.getExtendTypes();
     561 + if (extendTypes.size() != 1) {
     562 + return 0;
     563 + }
     564 + int fixed = 0;
     565 + ArgType extendType = extendTypes.get(0);
     566 + for (ITypeBound bound : casts) {
     567 + TypeBoundCheckCastAssign cast = (TypeBoundCheckCastAssign) bound;
     568 + ArgType castType = cast.getType();
     569 + TypeCompareEnum result = typeUpdate.getTypeCompare().compareTypes(extendType, castType);
     570 + if (result.isEqual() || result == TypeCompareEnum.NARROW_BY_GENERIC) {
     571 + cast.getInsn().updateIndex(bestType);
     572 + fixed++;
     573 + }
     574 + }
     575 + return fixed;
     576 + }
     577 + 
     578 + @SuppressWarnings({ "ForLoopReplaceableByWhile", "ForLoopReplaceableByForEach" })
    524 579   private boolean tryInsertCasts(MethodNode mth) {
    525 580   int added = 0;
    526 581   List<SSAVar> mthSVars = mth.getSVars();
    skipped 467 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/main/java/jadx/core/utils/ListUtils.java
    skipped 111 lines
    112 112   return list;
    113 113   }
    114 114   
    115  - public static <T> List<T> filter(List<T> list, Predicate<T> filter) {
     115 + public static <T> List<T> filter(Collection<T> list, Predicate<T> filter) {
    116 116   if (list == null || list.isEmpty()) {
    117 117   return Collections.emptyList();
    118 118   }
    skipped 29 lines
    148 148   return found;
    149 149   }
    150 150   
    151  - public static <T> boolean allMatch(List<T> list, Predicate<T> test) {
     151 + public static <T> boolean allMatch(Collection<T> list, Predicate<T> test) {
    152 152   if (list == null || list.isEmpty()) {
    153 153   return false;
    154 154   }
    skipped 5 lines
    160 160   return true;
    161 161   }
    162 162   
    163  - public static <T> boolean anyMatch(List<T> list, Predicate<T> test) {
     163 + public static <T> boolean anyMatch(Collection<T> list, Predicate<T> test) {
    164 164   if (list == null || list.isEmpty()) {
    165 165   return false;
    166 166   }
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver20.java
     1 +package jadx.tests.integration.types;
     2 + 
     3 +import java.util.Arrays;
     4 +import java.util.Iterator;
     5 +import java.util.List;
     6 + 
     7 +import org.junit.jupiter.api.Test;
     8 + 
     9 +import jadx.tests.api.SmaliTest;
     10 +import jadx.tests.api.extensions.profiles.TestProfile;
     11 +import jadx.tests.api.extensions.profiles.TestWithProfiles;
     12 + 
     13 +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
     14 + 
     15 +/**
     16 + * Issue 1238
     17 + */
     18 +public class TestTypeResolver20 extends SmaliTest {
     19 + 
     20 + public static class TestCls {
     21 + public interface Sequence<T> {
     22 + Iterator<T> iterator();
     23 + }
     24 + 
     25 + public static <T extends Comparable<? super T>> T max(Sequence<? extends T> seq) {
     26 + Iterator<? extends T> it = seq.iterator();
     27 + if (!it.hasNext()) {
     28 + return null;
     29 + }
     30 + T t = it.next();
     31 + while (it.hasNext()) {
     32 + T next = it.next();
     33 + if (t.compareTo(next) < 0) {
     34 + t = next;
     35 + }
     36 + }
     37 + return t;
     38 + }
     39 + 
     40 + private static class ArraySeq<T> implements Sequence<T> {
     41 + private final List<T> list;
     42 + 
     43 + @SafeVarargs
     44 + public ArraySeq(T... arr) {
     45 + this.list = Arrays.asList(arr);
     46 + }
     47 + 
     48 + @Override
     49 + public Iterator<T> iterator() {
     50 + return list.iterator();
     51 + }
     52 + }
     53 + 
     54 + public void check() {
     55 + assertThat(max(new ArraySeq<>(2, 5, 3, 4))).isEqualTo(5);
     56 + }
     57 + }
     58 + 
     59 + @TestWithProfiles({ TestProfile.DX_J8, TestProfile.JAVA8 })
     60 + public void test() {
     61 + noDebugInfo();
     62 + assertThat(getClassNode(TestCls.class))
     63 + .code()
     64 + .doesNotContain("next = next;")
     65 + .containsOne("T next = it.next();");
     66 + }
     67 + 
     68 + @Test
     69 + public void testSmali() {
     70 + assertThat(getClassNodeFromSmaliFiles())
     71 + .code()
     72 + .containsOne("T next = it.next();")
     73 + .containsOne("T next2 = it.next();");
     74 + }
     75 +}
     76 + 
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/smali/types/TestTypeResolver20/Sequence.smali
     1 +.class public interface abstract Lkotlin/sequences/Sequence;
     2 +.super Ljava/lang/Object;
     3 +.source "SourceFile"
     4 + 
     5 +.annotation system Ldalvik/annotation/Signature;
     6 + value = {
     7 + "<T:",
     8 + "Ljava/lang/Object;",
     9 + ">",
     10 + "Ljava/lang/Object;"
     11 + }
     12 +.end annotation
     13 + 
     14 +.method public abstract iterator()Ljava/util/Iterator;
     15 + .annotation system Ldalvik/annotation/Signature;
     16 + value = {
     17 + "()",
     18 + "Ljava/util/Iterator<",
     19 + "TT;>;"
     20 + }
     21 + .end annotation
     22 +.end method
     23 + 
  • ■ ■ ■ ■ ■ ■
    jadx-core/src/test/smali/types/TestTypeResolver20/TestTypeResolver20.smali
     1 +.class public Ltypes/TestTypeResolver20;
     2 +.super Ljava/lang/Object;
     3 +.source "SourceFile"
     4 + 
     5 + 
     6 +.method public static final max(Lkotlin/sequences/Sequence;)Ljava/lang/Comparable;
     7 + .registers 4
     8 + .annotation system Ldalvik/annotation/Signature;
     9 + value = {
     10 + "<T::",
     11 + "Ljava/lang/Comparable<",
     12 + "-TT;>;>(",
     13 + "Lkotlin/sequences/Sequence<",
     14 + "+TT;>;)TT;"
     15 + }
     16 + .end annotation
     17 + 
     18 + .line 1147
     19 + invoke-interface {p0}, Lkotlin/sequences/Sequence;->iterator()Ljava/util/Iterator;
     20 + move-result-object p0
     21 + 
     22 + .line 1148
     23 + invoke-interface {p0}, Ljava/util/Iterator;->hasNext()Z
     24 + move-result v0
     25 + 
     26 + if-nez v0, :cond_11
     27 + 
     28 + const/4 p0, 0x0
     29 + return-object p0
     30 + 
     31 + .line 1149
     32 + :cond_11
     33 + invoke-interface {p0}, Ljava/util/Iterator;->next()Ljava/lang/Object;
     34 + move-result-object v0
     35 + check-cast v0, Ljava/lang/Comparable;
     36 + 
     37 + .line 1150
     38 + :cond_17
     39 + :goto_17
     40 + invoke-interface {p0}, Ljava/util/Iterator;->hasNext()Z
     41 + move-result v1
     42 + 
     43 + if-eqz v1, :cond_2b
     44 + 
     45 + .line 1151
     46 + invoke-interface {p0}, Ljava/util/Iterator;->next()Ljava/lang/Object;
     47 + move-result-object v1
     48 + check-cast v1, Ljava/lang/Comparable;
     49 + 
     50 + .line 1152
     51 + invoke-interface {v0, v1}, Ljava/lang/Comparable;->compareTo(Ljava/lang/Object;)I
     52 + move-result v2
     53 + 
     54 + if-gez v2, :cond_17
     55 + 
     56 + move-object v0, v1
     57 + goto :goto_17
     58 + 
     59 + :cond_2b
     60 + return-object v0
     61 +.end method
     62 + 
Please wait...
Page is in error, reload to recover