From fef1ad08000692b3ceec588efff7f8287833fea6 Mon Sep 17 00:00:00 2001 From: Anairkoen Schno Date: Tue, 27 Apr 2021 22:00:23 -0500 Subject: [PATCH] Add explicit check for plugin resolution loops --- IPA.Loader/Loader/PluginLoader.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 7cead744..3b93e48c 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -816,6 +816,7 @@ namespace IPA.Loader var loadedPlugins = new Dictionary(); var outputOrder = new List(PluginsMetadata.Count); + var isProcessing = new HashSet(); { bool TryResolveId(string id, [MaybeNullWhen(false)] out PluginMetadata meta, out bool disabled, out bool ignored) @@ -846,6 +847,18 @@ namespace IPA.Loader void Resolve(PluginMetadata plugin, ref bool disabled, out bool ignored) { + // first we need to check for loops in the resolution graph to prevent stack overflows + if (isProcessing.Contains(plugin)) + { + Logger.loader.Error($"Loop detected while processing {plugin.Name}; flagging as ignored"); + // we can't safely add it to ignoredPlugins, because then when the ignore propagates up the stack, + // we may end up ignoring outselves again + ignored = true; + return; + } + + using var _removeProcessing = Utils.ScopeGuard(() => isProcessing.Remove(plugin)); + // if this method is being called, this is the first and only time that it has been called for this plugin. ignored = false;