Browse Source

Add explicit check for plugin resolution loops

pull/72/head
Anairkoen Schno 3 years ago
parent
commit
fef1ad0800
Signed by: DaNike GPG Key ID: BEFB74D5F3FC4387
1 changed files with 13 additions and 0 deletions
  1. +13
    -0
      IPA.Loader/Loader/PluginLoader.cs

+ 13
- 0
IPA.Loader/Loader/PluginLoader.cs View File

@ -816,6 +816,7 @@ namespace IPA.Loader
var loadedPlugins = new Dictionary<string, (PluginMetadata Meta, bool Disabled, bool Ignored)>(); var loadedPlugins = new Dictionary<string, (PluginMetadata Meta, bool Disabled, bool Ignored)>();
var outputOrder = new List<PluginMetadata>(PluginsMetadata.Count); var outputOrder = new List<PluginMetadata>(PluginsMetadata.Count);
var isProcessing = new HashSet<PluginMetadata>();
{ {
bool TryResolveId(string id, [MaybeNullWhen(false)] out PluginMetadata meta, out bool disabled, out bool ignored) 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) 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. // if this method is being called, this is the first and only time that it has been called for this plugin.
ignored = false; ignored = false;


Loading…
Cancel
Save