From 5ee9fe3573e0bc1b2803d722952e34acab216b26 Mon Sep 17 00:00:00 2001 From: Dean Marcussen Date: Tue, 3 Nov 2020 15:25:34 +0000 Subject: [PATCH 1/4] Limit content item recursions to 20 --- .../Liquid/BuildDisplayFilter.cs | 6 +++-- .../Liquid/ContentItemRecursionHelper.cs | 24 +++++++++++++++++-- .../OrchardCore.Contents/Startup.cs | 3 +-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs index b365682a9cb..6d3498cf1aa 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs @@ -14,6 +14,8 @@ namespace OrchardCore.Contents.Liquid { public class BuildDisplayFilter : ILiquidFilter { + private const int MaxContentItemRecursions = 20; + public ValueTask ProcessAsync(FluidValue input, FilterArguments arguments, TemplateContext ctx) { static async ValueTask Awaited(Task task) @@ -49,8 +51,8 @@ static async ValueTask Awaited(Task task) var buildDisplayRecursionHelper = serviceProvider.GetRequiredService>(); - // When {{ Model.ContentItem | shape_build_display | shape_render }} is called prevent recursion. - if (buildDisplayRecursionHelper.IsRecursive(contentItem)) + // When {{ Model.ContentItem | shape_build_display | shape_render }} is called prevent unlimited recursions. + if (buildDisplayRecursionHelper.IsRecursive(contentItem, MaxContentItemRecursions)) { return new ValueTask(NilValue.Instance); } diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs index 3a558e75ef6..e8ccc7218bc 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs @@ -13,19 +13,39 @@ public interface IContentItemRecursionHelper where T : ILiquidFilter /// /// Returns when the has already been evaluated during this request by the particular filter./> /// - bool IsRecursive(ContentItem contentItem); + bool IsRecursive(ContentItem contentItem, int maxRecursions = 1); } /// public class ContentItemRecursionHelper : IContentItemRecursionHelper where T : ILiquidFilter { private HashSet _contentItemIds = new HashSet(StringComparer.OrdinalIgnoreCase); + private Dictionary _recursions = new Dictionary(StringComparer.OrdinalIgnoreCase); /// - public bool IsRecursive(ContentItem contentItem) + public bool IsRecursive(ContentItem contentItem, int maxRecursions = 1) { if (_contentItemIds.Contains(contentItem.ContentItemId)) { + if (maxRecursions > 1) + { + if (_recursions.TryGetValue(contentItem.ContentItemId, out var counter)) + { + if (counter == maxRecursions) + { + return true; + } + + _recursions[contentItem.ContentItemId] = counter + 1; + return false; + } + else + { + _recursions[contentItem.ContentItemId] = 1; + return false; + } + } + return true; } diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs index 05dd8373f61..0d6178dca27 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Startup.cs @@ -140,8 +140,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddLiquidFilter("display_url"); services.AddLiquidFilter("full_text"); - services.AddScoped, ContentItemRecursionHelper>(); - services.AddScoped, ContentItemRecursionHelper>(); + services.AddScoped(typeof(IContentItemRecursionHelper<>), typeof(ContentItemRecursionHelper<>)); } public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) From fd4da5653ae2760a9042fcda4c78098e9b4f1282 Mon Sep 17 00:00:00 2001 From: Dean Marcussen Date: Wed, 4 Nov 2020 08:35:24 +0000 Subject: [PATCH 2/4] Compare by ref --- .../Liquid/BuildDisplayFilter.cs | 7 +++-- .../Liquid/ContentItemRecursionHelper.cs | 30 +++++-------------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs index 6d3498cf1aa..946efdc4040 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/BuildDisplayFilter.cs @@ -14,7 +14,7 @@ namespace OrchardCore.Contents.Liquid { public class BuildDisplayFilter : ILiquidFilter { - private const int MaxContentItemRecursions = 20; + private const int DefaultMaxContentItemRecursions = 20; public ValueTask ProcessAsync(FluidValue input, FilterArguments arguments, TemplateContext ctx) { @@ -52,7 +52,10 @@ static async ValueTask Awaited(Task task) var buildDisplayRecursionHelper = serviceProvider.GetRequiredService>(); // When {{ Model.ContentItem | shape_build_display | shape_render }} is called prevent unlimited recursions. - if (buildDisplayRecursionHelper.IsRecursive(contentItem, MaxContentItemRecursions)) + // max_recursions is an optional argument to override the default limit of 20. + var maxRecursions = arguments["max_recursions"]; + var recursionLimit = maxRecursions.Type == FluidValues.Number ? Convert.ToInt32(maxRecursions.ToNumberValue()) : DefaultMaxContentItemRecursions; + if (buildDisplayRecursionHelper.IsRecursive(contentItem, recursionLimit)) { return new ValueTask(NilValue.Instance); } diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs index e8ccc7218bc..a1c4fc0b33f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs @@ -19,38 +19,24 @@ public interface IContentItemRecursionHelper where T : ILiquidFilter /// public class ContentItemRecursionHelper : IContentItemRecursionHelper where T : ILiquidFilter { - private HashSet _contentItemIds = new HashSet(StringComparer.OrdinalIgnoreCase); - private Dictionary _recursions = new Dictionary(StringComparer.OrdinalIgnoreCase); + private Dictionary _recursions = new Dictionary(); /// public bool IsRecursive(ContentItem contentItem, int maxRecursions = 1) { - if (_contentItemIds.Contains(contentItem.ContentItemId)) + if (_recursions.ContainsKey(contentItem)) { - if (maxRecursions > 1) + var counter = _recursions[contentItem]; + if (counter == maxRecursions) { - if (_recursions.TryGetValue(contentItem.ContentItemId, out var counter)) - { - if (counter == maxRecursions) - { - return true; - } - - _recursions[contentItem.ContentItemId] = counter + 1; - return false; - } - else - { - _recursions[contentItem.ContentItemId] = 1; - return false; - } + return true; } - return true; + _recursions[contentItem] = counter + 1; + return false; } - _contentItemIds.Add(contentItem.ContentItemId); - + _recursions[contentItem] = 1; return false; } } From d0055e79c0dd91d21693ccb60be87aa527dab3a0 Mon Sep 17 00:00:00 2001 From: Dean Marcussen Date: Wed, 4 Nov 2020 10:00:54 +0000 Subject: [PATCH 3/4] Force max recursions to be at least 1 --- .../Liquid/ContentItemRecursionHelper.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs index a1c4fc0b33f..93d37df2371 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs @@ -27,6 +27,11 @@ public bool IsRecursive(ContentItem contentItem, int maxRecursions = 1) if (_recursions.ContainsKey(contentItem)) { var counter = _recursions[contentItem]; + if (maxRecursions < 1) + { + maxRecursions = 1; + } + if (counter == maxRecursions) { return true; From a2c7e9e44efaffc2b08f683f0c4fc4887ca44026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Thierry=20K=C3=A9chichian?= Date: Thu, 5 Nov 2020 00:25:58 +0100 Subject: [PATCH 4/4] Update ContentItemRecursionHelper.cs --- .../OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs index 93d37df2371..a0d78616374 100644 --- a/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs +++ b/src/OrchardCore.Modules/OrchardCore.Contents/Liquid/ContentItemRecursionHelper.cs @@ -32,7 +32,7 @@ public bool IsRecursive(ContentItem contentItem, int maxRecursions = 1) maxRecursions = 1; } - if (counter == maxRecursions) + if (counter > maxRecursions) { return true; }