feat: allow to change limit for type inference updates (PR #2629)

* Fix Type inference error: updates count limit reached

* Fix for the "Type inference error: updates count limit reached"
* Users will be able to choose the limit and possibly avoid this error
* Adding options on decompilation settings

* Updating README.md with new type update limit parameter

Updating README.md with new type update limit parameter
This commit is contained in:
Away
2025-09-09 21:50:04 +02:00
committed by GitHub
parent 2cd112cd3d
commit f61d90ec2f
16 changed files with 53 additions and 4 deletions
+1
View File
@@ -161,6 +161,7 @@ options:
'auto' - automatically select (default)
'decimal' - use decimal
'hexadecimal' - use hexadecimal
-tul, --type-update-limit - type update limit count
--fs-case-sensitive - treat filesystem as case sensitive, false by default
--cfg - save methods control flow graph to dot file
--raw-cfg - save methods control flow graph (use raw instructions)
@@ -59,6 +59,9 @@ public class JadxCLIArgs {
@Parameter(names = { "-j", "--threads-count" }, description = "processing threads count")
protected int threadsCount = JadxArgs.DEFAULT_THREADS_COUNT;
@Parameter(names = { "-tul", "--type-update-limit" }, description = "type update limit count")
protected int typeUpdatesLimitCount = 0;
@Parameter(names = { "--single-class" }, description = "decompile a single class, full name, raw or alias")
protected String singleClass = null;
@@ -384,6 +387,7 @@ public class JadxCLIArgs {
args.setFsCaseSensitive(fsCaseSensitive);
args.setCommentsLevel(commentsLevel);
args.setIntegerFormat(integerFormat);
args.setTypeUpdatesLimitCount(typeUpdatesLimitCount);
args.setUseDxInput(useDx);
args.setPluginOptions(pluginOptions);
args.setDisabledPlugins(Arrays.stream(disablePlugins.split(",")).map(String::trim).collect(Collectors.toSet()));
@@ -549,6 +553,10 @@ public class JadxCLIArgs {
return integerFormat;
}
public int getTypeUpdatesLimitCount() {
return typeUpdatesLimitCount;
}
public boolean isEscapeUnicode() {
return escapeUnicode;
}
@@ -167,6 +167,8 @@ public class JadxArgs implements Closeable {
private IntegerFormat integerFormat = IntegerFormat.AUTO;
private int typeUpdatesLimitCount = 0;
private boolean useDxInput = false;
public enum UseKotlinMethodsForVarNames {
@@ -738,6 +740,14 @@ public class JadxArgs implements Closeable {
this.integerFormat = format;
}
public int getTypeUpdatesLimitCount() {
return typeUpdatesLimitCount;
}
public void setTypeUpdatesLimitCount(int typeUpdatesLimitCount) {
this.typeUpdatesLimitCount = typeUpdatesLimitCount;
}
public boolean isUseDxInput() {
return useDxInput;
}
@@ -898,6 +908,7 @@ public class JadxArgs implements Closeable {
+ ", cfgOutput=" + cfgOutput
+ ", rawCFGOutput=" + rawCFGOutput
+ ", useHeadersForDetectResourceExtensions=" + useHeadersForDetectResourceExtensions
+ ", typeUpdatesLimitCount=" + typeUpdatesLimitCount
+ '}';
}
}
@@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.api.JadxArgs;
import jadx.core.Consts;
import jadx.core.clsp.ClspClass;
import jadx.core.dex.attributes.AFlag;
@@ -42,9 +43,11 @@ public final class TypeUpdate {
private final RootNode root;
private final Map<InsnType, ITypeListener> listenerRegistry;
private final TypeCompare comparator;
private final JadxArgs args;
public TypeUpdate(RootNode root) {
this.root = root;
this.args = root.getArgs();
this.listenerRegistry = initListenerRegistry();
this.comparator = new TypeCompare(root);
}
@@ -79,7 +82,7 @@ public final class TypeUpdate {
return REJECT;
}
TypeUpdateInfo updateInfo = new TypeUpdateInfo(mth, flags);
TypeUpdateInfo updateInfo = new TypeUpdateInfo(mth, flags, args);
TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType);
if (result == REJECT) {
return result;
@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import jadx.api.JadxArgs;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.nodes.MethodNode;
@@ -18,10 +19,10 @@ public class TypeUpdateInfo {
private final int updatesLimitCount;
private int updateSeq = 0;
public TypeUpdateInfo(MethodNode mth, TypeUpdateFlags flags) {
public TypeUpdateInfo(MethodNode mth, TypeUpdateFlags flags, JadxArgs args) {
this.mth = mth;
this.flags = flags;
this.updatesLimitCount = mth.getInsnsCount() * 10;
this.updatesLimitCount = mth.getInsnsCount() * (10 + args.getTypeUpdatesLimitCount());
}
public void requestUpdate(InsnArg arg, ArgType changeType) {
@@ -32,7 +33,8 @@ public class TypeUpdateInfo {
+ ", insn: " + arg.getParentInsn());
}
if (updateSeq > updatesLimitCount) {
throw new JadxOverflowException("Type inference error: updates count limit reached");
throw new JadxOverflowException("Type inference error: updates count limit reached"
+ " with updateSeq = " + updateSeq + ". Try increasing the type limit count on preferences.");
}
}
@@ -740,6 +740,10 @@ public class JadxSettings extends JadxCLIArgs {
this.integerFormat = format;
}
public void setTypeUpdatesLimitCount(int typeUpdatesLimitCount) {
this.typeUpdatesLimitCount = typeUpdatesLimitCount;
}
public void setLineNumbersMode(LineNumbersMode lineNumbersMode) {
this.lineNumbersMode = lineNumbersMode;
}
@@ -640,6 +640,16 @@ public class JadxSettingsWindow extends JDialog {
needReload();
});
int typeUpdatesLimitValue = settings.getTypeUpdatesLimitCount();
int typeUpdatesLimitCountMax = (int) Math.pow(2, 32);
SpinnerNumberModel typeUpdatesLimitCountSpinnerModel =
new SpinnerNumberModel(typeUpdatesLimitValue, 0, typeUpdatesLimitCountMax, 1);
JSpinner typeUpdatesLimitCount = new JSpinner(typeUpdatesLimitCountSpinnerModel);
typeUpdatesLimitCount.addChangeListener(e -> {
settings.setTypeUpdatesLimitCount((Integer) typeUpdatesLimitCount.getValue());
needReload();
});
SettingsGroup other = new SettingsGroup(NLS.str("preferences.decompile"));
other.addRow(NLS.str("preferences.threads"), threadsCount);
other.addRow(NLS.str("preferences.excludedPackages"),
@@ -664,6 +674,7 @@ public class JadxSettingsWindow extends JDialog {
other.addRow(NLS.str("preferences.useKotlinMethodsForVarNames"), kotlinRenameVars);
other.addRow(NLS.str("preferences.commentsLevel"), commentsLevel);
other.addRow(NLS.str("preferences.integerFormat"), integerFormat);
other.addRow(NLS.str("preferences.typeUpdatesCountLimit"), typeUpdatesLimitCount);
return other;
}
@@ -269,6 +269,7 @@ preferences.xposed_codegen_language=Xposed-Code-Generierungssprache
preferences.update_channel=Jadx-Updatekanal
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=Ganzzahlformat
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Schriftart ändern
preferences.smali_font=Monospaced-Schriftart (Smali/Hex)
preferences.laf_theme=Thema
@@ -269,6 +269,7 @@ preferences.xposed_codegen_language=Xposed code generation language
preferences.update_channel=Jadx update channel
preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=Integer format
preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Editor font
preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=Theme
@@ -269,6 +269,7 @@ preferences.raw_cfg=Generate RAW CFG graphs
#preferences.update_channel=Jadx update channel
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Fuente del editor
#preferences.smali_font=Monospaced font (Smali/Hex)
#preferences.laf_theme=Theme
@@ -269,6 +269,7 @@ preferences.raw_cfg=Hasilkan grafik CFG mentah
#preferences.update_channel=Jadx update channel
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=Format bilangan bulat
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Font editor
preferences.smali_font=Font monospasi (Smali/Hex)
preferences.laf_theme=Tema
@@ -269,6 +269,7 @@ preferences.raw_cfg=RAW CFG 그래프 생성
#preferences.update_channel=Jadx update channel
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=에디터 글씨체
#preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=테마
@@ -269,6 +269,7 @@ preferences.raw_cfg=Gera gráficos CFG no formato RAW
#preferences.update_channel=Jadx update channel
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Fonte do editor
#preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=Tema
@@ -269,6 +269,7 @@ preferences.xposed_codegen_language=Язык генерации Xposed хуко
preferences.update_channel=Канал обновления Jadx
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=Формат чисел
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=Шрифт редактора Java
preferences.smali_font=Шрифт smali/HEX редактора
preferences.laf_theme=Тема приложения
@@ -269,6 +269,7 @@ preferences.xposed_codegen_language=Xposed代码生成语言
preferences.update_channel=Jadx 更新通道
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=数值格式化
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=编辑器字体
preferences.smali_font=等宽字体 (Smali/Hex)
preferences.laf_theme=主题
@@ -269,6 +269,7 @@ preferences.xposed_codegen_language=Xposed 程式碼產生語言
preferences.update_channel=Jadx 更新頻道
#preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=整數模式
#preferences.typeUpdatesCountLimit=Update type limit count
preferences.font=編輯器字型
preferences.smali_font=等寬字型 (Smali/Hex)
preferences.laf_theme=主題