mirror of
https://github.com/2dust/v2rayN.git
synced 2025-10-13 20:09:12 +00:00
Avoids circular dependency in profile groups
Adds cycle detection to prevent infinite loops when evaluating profile groups. This ensures that profile group configurations don't result in stack overflow errors when groups reference each other, directly or indirectly.
This commit is contained in:
parent
f64f72ba7f
commit
142940118e
3 changed files with 50 additions and 2 deletions
|
@ -109,6 +109,42 @@ public class ProfileItem : ReactiveObject
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> HasCycle(HashSet<string> visited, HashSet<string> stack)
|
||||||
|
{
|
||||||
|
if (ConfigType < EConfigType.Group)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (stack.Contains(IndexId))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (visited.Contains(IndexId))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
visited.Add(IndexId);
|
||||||
|
stack.Add(IndexId);
|
||||||
|
|
||||||
|
if (ProfileGroupItemManager.Instance.TryGet(IndexId, out var group)
|
||||||
|
&& !group.ChildItems.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
var childProfiles = (await Task.WhenAll(
|
||||||
|
Utils.String2List(group.ChildItems)
|
||||||
|
.Where(p => !p.IsNullOrEmpty())
|
||||||
|
.Select(AppManager.Instance.GetProfileItem)
|
||||||
|
))
|
||||||
|
.Where(p => p != null)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var child in childProfiles)
|
||||||
|
{
|
||||||
|
if (await child.HasCycle(visited, stack))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack.Remove(IndexId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#endregion function
|
#endregion function
|
||||||
|
|
||||||
[PrimaryKey]
|
[PrimaryKey]
|
||||||
|
|
|
@ -217,9 +217,15 @@ public partial class CoreConfigSingboxService
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasCycle = await node.HasCycle(new HashSet<string>(), new HashSet<string>());
|
||||||
|
if (hasCycle)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// remove custom nodes
|
// remove custom nodes
|
||||||
// remove group nodes for proxy chain
|
// remove group nodes for proxy chain
|
||||||
// avoid self-reference
|
|
||||||
var childProfiles = (await Task.WhenAll(
|
var childProfiles = (await Task.WhenAll(
|
||||||
Utils.String2List(profileGroupItem.ChildItems)
|
Utils.String2List(profileGroupItem.ChildItems)
|
||||||
.Where(p => !p.IsNullOrEmpty())
|
.Where(p => !p.IsNullOrEmpty())
|
||||||
|
@ -230,7 +236,6 @@ public partial class CoreConfigSingboxService
|
||||||
&& p.IsValid()
|
&& p.IsValid()
|
||||||
&& p.ConfigType != EConfigType.Custom
|
&& p.ConfigType != EConfigType.Custom
|
||||||
&& (node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
|
&& (node.ConfigType == EConfigType.PolicyGroup || p.ConfigType < EConfigType.Group)
|
||||||
&& p.IndexId != node.IndexId
|
|
||||||
)
|
)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
|
|
@ -493,6 +493,13 @@ public partial class CoreConfigV2rayService
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasCycle = await node.HasCycle(new HashSet<string>(), new HashSet<string>());
|
||||||
|
if (hasCycle)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// remove custom nodes
|
// remove custom nodes
|
||||||
// remove group nodes for proxy chain
|
// remove group nodes for proxy chain
|
||||||
var childProfiles = (await Task.WhenAll(
|
var childProfiles = (await Task.WhenAll(
|
||||||
|
|
Loading…
Reference in a new issue