diff --git a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java index 9a8b0883b..af5fa882f 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/ClassGen.java @@ -329,10 +329,10 @@ public class ClassGen { } } - private void insertDecompilationProblems(CodeWriter code, AttrNode node) { + public void insertDecompilationProblems(CodeWriter code, AttrNode node) { List errors = node.getAll(AType.JADX_ERROR); if (!errors.isEmpty()) { - errors.stream().sorted().forEach(err -> { + errors.stream().distinct().sorted().forEach(err -> { code.startLine("/* JADX ERROR: ").add(err.getError()); Throwable cause = err.getCause(); if (cause != null) { diff --git a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java index ed1500fe0..43de06422 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/MethodGen.java @@ -30,6 +30,7 @@ import jadx.core.utils.InsnUtils; import jadx.core.utils.Utils; import jadx.core.utils.exceptions.CodegenException; import jadx.core.utils.exceptions.DecodeException; +import jadx.core.utils.exceptions.JadxOverflowException; public class MethodGen { private static final Logger LOG = LoggerFactory.getLogger(MethodGen.class); @@ -197,8 +198,18 @@ public class MethodGen { .add(mth.getMethodInfo().getReturnType().toString()) .add("\");"); } else { - RegionGen regionGen = new RegionGen(this); - regionGen.makeRegion(code, mth.getRegion()); + try { + RegionGen regionGen = new RegionGen(this); + regionGen.makeRegion(code, mth.getRegion()); + } catch (StackOverflowError | BootstrapMethodError e) { + mth.addError("Method code generation error", new JadxOverflowException("StackOverflow")); + classGen.insertDecompilationProblems(code, mth); + addInstructions(code); + } catch (Exception e) { + mth.addError("Method code generation error", e); + classGen.insertDecompilationProblems(code, mth); + addInstructions(code); + } } } diff --git a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java index 913927eee..d42cfdd0f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java +++ b/jadx-core/src/main/java/jadx/core/dex/attributes/nodes/JadxError.java @@ -1,18 +1,18 @@ package jadx.core.dex.attributes.nodes; +import java.util.Objects; + +import org.jetbrains.annotations.NotNull; + import jadx.core.utils.Utils; -public class JadxError { +public class JadxError implements Comparable { private final String error; private final Throwable cause; - public JadxError(Throwable cause) { - this(null, cause); - } - public JadxError(String error, Throwable cause) { - this.error = error; + this.error = Objects.requireNonNull(error); this.cause = cause; } @@ -24,6 +24,28 @@ public class JadxError { return cause; } + @Override + public int compareTo(@NotNull JadxError o) { + return this.error.compareTo(o.getError()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + JadxError other = (JadxError) o; + return error.equals(other.error); + } + + @Override + public int hashCode() { + return error.hashCode(); + } + @Override public String toString() { StringBuilder str = new StringBuilder(); diff --git a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java index 9991f1e5b..1a446b728 100644 --- a/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java +++ b/jadx-core/src/main/java/jadx/core/dex/nodes/MethodNode.java @@ -659,7 +659,7 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode { LOG.info("{} in {}", commentStr, this); } - public void addError(String errStr, Exception e) { + public void addError(String errStr, Throwable e) { ErrorsCounter.methodError(this, errStr, e); } @@ -667,6 +667,20 @@ public class MethodNode extends LineAttrNode implements ILoadable, ICodeNode { return mthInfo; } + /** + * Stat method. + * Calculate instructions count as a measure of method size + */ + public long countInsns() { + if (instructions != null) { + return instructions.length; + } + if (blocks != null) { + return blocks.stream().mapToLong(block -> block.getInstructions().size()).sum(); + } + return -1; + } + @Override public int hashCode() { return mthInfo.hashCode(); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java index 4a1673bf9..515e6d4f3 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/debuginfo/DebugInfoApplyVisitor.java @@ -143,7 +143,7 @@ public class DebugInfoApplyVisitor extends AbstractVisitor { public static void applyDebugInfo(MethodNode mth, SSAVar ssaVar, ArgType type, String varName) { TypeUpdateResult result = mth.root().getTypeUpdate().applyWithWiderAllow(ssaVar, type); if (result == TypeUpdateResult.REJECT) { - if (LOG.isDebugEnabled()) { + if (Consts.DEBUG) { LOG.debug("Reject debug info of type: {} and name: '{}' for {}, mth: {}", type, varName, ssaVar, mth); } } else { 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 277048791..f0c39d29c 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 @@ -232,7 +232,9 @@ public class TypeSearch { int size = candidateTypes.size(); if (size == 0) { throw new JadxRuntimeException("No candidate types for var: " + ssaVar.getDetailedVarInfo(mth) - + "\n assigns: " + assigns + "\n uses: " + uses); + + "\n assigns: " + assigns + + "\n uses: " + uses + + "\n mth insns count: " + mth.countInsns()); } if (size == 1) { varInfo.setTypeResolved(true);