From c6e0c1e4903f72bb8ae7f0c274634939d76863a7 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 8 Jan 2014 13:00:53 -0500 Subject: [PATCH 1/2] Fix resource counting bug with respond_to?(:length) --- lib/liquid/block.rb | 2 +- lib/liquid/context.rb | 8 ++++++++ lib/liquid/tags/assign.rb | 2 +- lib/liquid/tags/capture.rb | 2 +- test/liquid/template_test.rb | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index 0281b91..d1356eb 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -135,7 +135,7 @@ module Liquid end token_output = (token.respond_to?(:render) ? token.render(context) : token) - context.resource_limits[:render_length_current] += (token_output.respond_to?(:length) ? token_output.length : 1) + context.increment_used_resources(:render_length_current, token_output) if context.resource_limits_reached? context.resource_limits[:reached] = true raise MemoryError.new("Memory limits exceeded") diff --git a/lib/liquid/context.rb b/lib/liquid/context.rb index 2687dab..ade5c6d 100644 --- a/lib/liquid/context.rb +++ b/lib/liquid/context.rb @@ -28,6 +28,14 @@ module Liquid @filters = [] end + def increment_used_resources(key, obj) + @resource_limits[key] += if obj.class.ancestors & [ String, Array, Hash ] != [] + obj.length + else + 1 + end + end + def resource_limits_reached? (@resource_limits[:render_length_limit] && @resource_limits[:render_length_current] > @resource_limits[:render_length_limit]) || (@resource_limits[:render_score_limit] && @resource_limits[:render_score_current] > @resource_limits[:render_score_limit] ) || diff --git a/lib/liquid/tags/assign.rb b/lib/liquid/tags/assign.rb index 0af0976..4699a6a 100644 --- a/lib/liquid/tags/assign.rb +++ b/lib/liquid/tags/assign.rb @@ -25,7 +25,7 @@ module Liquid def render(context) val = @from.render(context) context.scopes.last[@to] = val - context.resource_limits[:assign_score_current] += (val.respond_to?(:length) ? val.length : 1) + context.increment_used_resources(:assign_score_current, val) '' end diff --git a/lib/liquid/tags/capture.rb b/lib/liquid/tags/capture.rb index 92b9950..34036be 100644 --- a/lib/liquid/tags/capture.rb +++ b/lib/liquid/tags/capture.rb @@ -27,7 +27,7 @@ module Liquid def render(context) output = super context.scopes.last[@to] = output - context.resource_limits[:assign_score_current] += (output.respond_to?(:length) ? output.length : 1) + context.increment_used_resources(:assign_score_current, output) '' end diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 5fd4d1e..f9afac1 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -14,6 +14,14 @@ class TemplateContextDrop < Liquid::Drop end end +class SomethingWithLength + def length + nil + end + + liquid_methods :length +end + class TemplateTest < Test::Unit::TestCase include Liquid @@ -86,6 +94,12 @@ class TemplateTest < Test::Unit::TestCase @global = nil end + def test_resource_limits_works_with_custom_length_method + t = Template.parse("{% assign foo = bar %}") + t.resource_limits = { :render_length_limit => 42 } + assert_equal "", t.render("bar" => SomethingWithLength.new) + end + def test_resource_limits_render_length t = Template.parse("0123456789") t.resource_limits = { :render_length_limit => 5 } From 62a86a25aec745466c8bb372680ab19082245827 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Wed, 8 Jan 2014 13:37:24 -0500 Subject: [PATCH 2/2] update history --- History.md | 1 + 1 file changed, 1 insertion(+) diff --git a/History.md b/History.md index 4b114c1..8b77e2a 100644 --- a/History.md +++ b/History.md @@ -3,6 +3,7 @@ ## 3.0.0 / not yet released / branch "master" * ... +* Fix resource counting bug with respond_to?(:length), see #263 [Florian Weingarten, fw42] * Allow specifying custom patterns for template filenames, see #284 [Andrei Gladkyi, agladkyi] * Allow drops to optimize loading a slice of elements, see #282 [Tom Burns, boourns] * Support for passing variables to snippets in subdirs, see #271 [Joost Hietbrink, joost]