From 198f0aa3667b6b36942b660d297c525e23b871d7 Mon Sep 17 00:00:00 2001 From: Justin Li Date: Mon, 1 Feb 2016 10:58:26 -0500 Subject: [PATCH 1/3] Add test for nested assign score bookkeeping --- test/integration/template_test.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/integration/template_test.rb b/test/integration/template_test.rb index c1e2ef3c..1e563dae 100644 --- a/test/integration/template_test.rb +++ b/test/integration/template_test.rb @@ -133,6 +133,17 @@ class TemplateTest < Minitest::Test refute_nil t.resource_limits.assign_score end + def test_resource_limits_assign_score_nested + t = Template.parse("{% assign foo = 'aaaa' | reverse %}") + + t.resource_limits.assign_score_limit = 3 + assert_equal "Liquid error: Memory limits exceeded", t.render + assert t.resource_limits.reached? + + t.resource_limits.assign_score_limit = 5 + assert_equal "", t.render! + end + def test_resource_limits_aborts_rendering_after_first_error t = Template.parse("{% for a in (1..100) %} foo1 {% endfor %} bar {% for a in (1..100) %} foo2 {% endfor %}") t.resource_limits.render_score_limit = 50 From 3891f14a1aebe3bcf45e6718b16ca85ca5f1566a Mon Sep 17 00:00:00 2001 From: Justin Li Date: Mon, 1 Feb 2016 11:00:49 -0500 Subject: [PATCH 2/3] Take nested values into account for assign score --- lib/liquid/tags/assign.rb | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 9cfb478a..78b86c1e 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -23,16 +23,25 @@ module Liquid def render(context) val = @from.render(context) context.scopes.last[@to] = val - - inc = val.instance_of?(String) || val.instance_of?(Array) || val.instance_of?(Hash) ? val.length : 1 - context.resource_limits.assign_score += inc - + context.resource_limits.assign_score += assign_score_of(val) ''.freeze end def blank? true end + + private + + def assign_score_of(val) + if val.instance_of?(String) + val.length + elsif val.instance_of?(Array) || val.instance_of?(Hash) + val.reduce(0) { |n, child| n + assign_score_of(child) } + else + 1 + end + end end Template.register_tag('assign'.freeze, Assign) From 60b508b151d8b6f786b2d586109f737f892ccf92 Mon Sep 17 00:00:00 2001 From: Justin Li Date: Mon, 1 Feb 2016 11:26:45 -0500 Subject: [PATCH 3/3] Use #each to avoid extra allocations --- lib/liquid/tags/assign.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 78b86c1e..f6cd5fad 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -37,7 +37,10 @@ module Liquid if val.instance_of?(String) val.length elsif val.instance_of?(Array) || val.instance_of?(Hash) - val.reduce(0) { |n, child| n + assign_score_of(child) } + sum = 1 + # Uses #each to avoid extra allocations. + val.each { |child| sum += assign_score_of(child) } + sum else 1 end