From 9075b428b143827c467e33fec2816423b1265b88 Mon Sep 17 00:00:00 2001 From: Florian Weingarten Date: Fri, 31 May 2013 09:25:25 -0400 Subject: [PATCH] Resource limits: Don't raise Error but render error message (but abort after first error) --- lib/liquid/block.rb | 4 ++-- lib/liquid/template.rb | 4 +++- test/liquid/template_test.rb | 21 +++++++++++++++++---- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/liquid/block.rb b/lib/liquid/block.rb index 9f888811..efd149be 100644 --- a/lib/liquid/block.rb +++ b/lib/liquid/block.rb @@ -108,9 +108,9 @@ module Liquid 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) - raise Liquid::MemoryError, context.resource_limits if context.resource_limits_reached? + raise MemoryError.new("Memory limits exceeded") if context.resource_limits_reached? output << token_output - rescue Liquid::MemoryError => e + rescue MemoryError => e raise e rescue ::StandardError => e output << (context.handle_error(e)) diff --git a/lib/liquid/template.rb b/lib/liquid/template.rb index 43c9318a..10a78049 100644 --- a/lib/liquid/template.rb +++ b/lib/liquid/template.rb @@ -120,9 +120,11 @@ module Liquid begin # render the nodelist. - # for performance reasons we get a array back here. join will make a string out of it + # for performance reasons we get an array back here. join will make a string out of it. result = @root.render(context) result.respond_to?(:join) ? result.join : result + rescue Liquid::MemoryError => e + context.handle_error(e) ensure @errors = context.errors end diff --git a/test/liquid/template_test.rb b/test/liquid/template_test.rb index 4e912c98..bc1c9a32 100644 --- a/test/liquid/template_test.rb +++ b/test/liquid/template_test.rb @@ -72,26 +72,39 @@ class TemplateTest < Test::Unit::TestCase @global = nil end - def test_resource_limits + def test_resource_limits_render_length t = Template.parse("0123456789") t.resource_limits = { :render_length_limit => 5 } - assert_raises(Liquid::MemoryError) { t.render() } + assert_equal "Liquid error: Memory limits exceeded", t.render() t.resource_limits = { :render_length_limit => 10 } assert_equal "0123456789", t.render() assert_not_nil t.resource_limits[:render_length_current] + end + def test_resource_limits_render_score + t = Template.parse("{% for a in (1..10) %} {% for a in (1..10) %} foo {% endfor %} {% endfor %}") + t.resource_limits = { :render_score_limit => 50 } + assert_equal "Liquid error: Memory limits exceeded", t.render() t = Template.parse("{% for a in (1..100) %} foo {% endfor %}") t.resource_limits = { :render_score_limit => 50 } - assert_raises(Liquid::MemoryError) { t.render() } + assert_equal "Liquid error: Memory limits exceeded", t.render() t.resource_limits = { :render_score_limit => 200 } assert_equal (" foo " * 100), t.render() assert_not_nil t.resource_limits[:render_score_current] + end + def test_resource_limits_assign_score t = Template.parse("{% assign foo = 42 %}{% assign bar = 23 %}") t.resource_limits = { :assign_score_limit => 1 } - assert_raises(Liquid::MemoryError) { t.render() } + assert_equal "Liquid error: Memory limits exceeded", t.render() t.resource_limits = { :assign_score_limit => 2 } assert_equal "", t.render() assert_not_nil t.resource_limits[:assign_score_current] 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 } + assert_equal "Liquid error: Memory limits exceeded", t.render() + end end # TemplateTest