diff --git a/lib/liquid/condition.rb b/lib/liquid/condition.rb index 7db9cf3..261eb3f 100644 --- a/lib/liquid/condition.rb +++ b/lib/liquid/condition.rb @@ -7,6 +7,7 @@ module Liquid # c.evaluate #=> true # class Condition #:nodoc: + @@depth = 0 @@operators = { '=='.freeze => ->(cond, left, right) { cond.send(:equal_variables, left, right) }, '!='.freeze => ->(cond, left, right) { !cond.send(:equal_variables, left, right) }, @@ -47,6 +48,11 @@ module Liquid when :or result || @child_condition.evaluate(context) when :and + @@depth += 1 + if @@depth >= 500 + @@depth = 0 + raise StackLevelError, "Nesting too deep".freeze + end result && @child_condition.evaluate(context) else result diff --git a/test/unit/condition_unit_test.rb b/test/unit/condition_unit_test.rb index 6b0cc34..5375259 100644 --- a/test/unit/condition_unit_test.rb +++ b/test/unit/condition_unit_test.rb @@ -130,6 +130,17 @@ class ConditionUnitTest < Minitest::Test assert_equal false, condition.evaluate end + def test_maximum_recursion_depth + condition = Condition.new(1, '==', 1) + + assert_raises(Liquid::StackLevelError) do + (1..510).each do + condition.evaluate + condition.and Condition.new(2, '==', 2) + end + end + end + def test_should_allow_custom_proc_operator Condition.operators['starts_with'] = proc { |cond, left, right| left =~ %r{^#{right}} }