diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeSearch.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeSearch.java index 88a70f24d..277048791 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeSearch.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeSearch.java @@ -89,6 +89,9 @@ public class TypeSearch { applySuccess = false; } } + if (!applySuccess) { + LOG.warn("Multi-variable search result apply rejected in {}", mth); + } return applySuccess; } diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java index 794c529c6..746f2350b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdate.java @@ -31,11 +31,12 @@ import static jadx.core.dex.visitors.typeinference.TypeUpdateResult.SAME; public final class TypeUpdate { private static final Logger LOG = LoggerFactory.getLogger(TypeUpdate.class); + private static final TypeUpdateFlags FLAGS_EMPTY = new TypeUpdateFlags(); + private static final TypeUpdateFlags FLAGS_WIDER = new TypeUpdateFlags().allowWider(); + private final Map listenerRegistry; private final TypeCompare comparator; - private ThreadLocal allowWider = new ThreadLocal<>(); - public TypeUpdate(RootNode root) { this.listenerRegistry = initListenerRegistry(); this.comparator = new TypeCompare(root); @@ -45,14 +46,22 @@ public final class TypeUpdate { * Perform recursive type checking and type propagation for all related variables */ public TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType) { - if (candidateType == null) { - return REJECT; - } - if (!candidateType.isTypeKnown()/* && ssaVar.getTypeInfo().getType().isTypeKnown() */) { + return apply(ssaVar, candidateType, FLAGS_EMPTY); + } + + /** + * Allow wider types for apply from debug info and some special cases + */ + public TypeUpdateResult applyWithWiderAllow(SSAVar ssaVar, ArgType candidateType) { + return apply(ssaVar, candidateType, FLAGS_WIDER); + } + + private TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType, TypeUpdateFlags flags) { + if (candidateType == null || !candidateType.isTypeKnown()) { return REJECT; } - TypeUpdateInfo updateInfo = new TypeUpdateInfo(); + TypeUpdateInfo updateInfo = new TypeUpdateInfo(flags); TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType); if (result == REJECT) { return result; @@ -61,7 +70,7 @@ public final class TypeUpdate { if (updates.isEmpty()) { return SAME; } - if (Consts.DEBUG && LOG.isDebugEnabled()) { + if (Consts.DEBUG) { LOG.debug("Applying types, init for {} -> {}", ssaVar, candidateType); updates.forEach(updateEntry -> LOG.debug(" {} -> {}", updateEntry.getType(), updateEntry.getArg())); } @@ -69,18 +78,6 @@ public final class TypeUpdate { return CHANGED; } - /** - * Allow wider types for apply from debug info and some special cases - */ - public TypeUpdateResult applyWithWiderAllow(SSAVar ssaVar, ArgType candidateType) { - try { - allowWider.set(true); - return apply(ssaVar, candidateType); - } finally { - allowWider.set(false); - } - } - private TypeUpdateResult updateTypeChecked(TypeUpdateInfo updateInfo, InsnArg arg, ArgType candidateType) { if (candidateType == null) { throw new JadxRuntimeException("Null type update for arg: " + arg); @@ -100,13 +97,11 @@ public final class TypeUpdate { } return SAME; } - if (compareResult.isWider()) { - if (allowWider.get() != Boolean.TRUE) { - if (Consts.DEBUG) { - LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType); - } - return REJECT; + if (compareResult.isWider() && !updateInfo.getFlags().isAllowWider()) { + if (Consts.DEBUG) { + LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType); } + return REJECT; } if (arg instanceof RegisterArg) { RegisterArg reg = (RegisterArg) arg; @@ -278,7 +273,8 @@ public final class TypeUpdate { if (changeArg.getType().isTypeKnown()) { // allow result to be wider TypeCompareEnum compareTypes = comparator.compareTypes(candidateType, changeArg.getType()); - boolean correctType = assignChanged ? compareTypes.isWider() : compareTypes.isNarrow(); + boolean correctType = compareTypes == TypeCompareEnum.EQUAL + || (assignChanged ? compareTypes.isWider() : compareTypes.isNarrow()); if (correctType && inBounds(changeArg, candidateType)) { allowReject = true; } else { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateFlags.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateFlags.java new file mode 100644 index 000000000..cfc8b24aa --- /dev/null +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateFlags.java @@ -0,0 +1,15 @@ +package jadx.core.dex.visitors.typeinference; + +public class TypeUpdateFlags { + + private boolean allowWider; + + public TypeUpdateFlags allowWider() { + this.allowWider = true; + return this; + } + + public boolean isAllowWider() { + return allowWider; + } +} diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateInfo.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateInfo.java index 3496669ab..b6e31df7b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateInfo.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeUpdateInfo.java @@ -7,8 +7,13 @@ import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; public class TypeUpdateInfo { + private final TypeUpdateFlags flags; private final List updates = new ArrayList<>(); + public TypeUpdateInfo(TypeUpdateFlags flags) { + this.flags = flags; + } + public void requestUpdate(InsnArg arg, ArgType changeType) { updates.add(new TypeUpdateEntry(arg, changeType)); } @@ -32,4 +37,8 @@ public class TypeUpdateInfo { public List getUpdates() { return updates; } + + public TypeUpdateFlags getFlags() { + return flags; + } }