Skip to content

Commit

Permalink
Fix some internal errors in filters from invalid input. (#1476)
Browse files Browse the repository at this point in the history
These fixes came from improving the corresponding test, so these might not
actually be causing problems in practice.
  • Loading branch information
dylanahsmith authored Feb 24, 2022
1 parent 15eaa49 commit 0d5e01a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 29 deletions.
6 changes: 6 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Liquid Change Log

## 5.1.1 (unreleased)

### Fixes

* Fix some internal errors in filters from invalid input [Dylan Thacker-Smith]

## 5.1.0 / 2021-09-09

### Features
Expand Down
48 changes: 33 additions & 15 deletions lib/liquid/standardfilters.rb
Original file line number Diff line number Diff line change
Expand Up @@ -213,17 +213,23 @@ def where(input, property, target_value = nil)

if ary.empty?
[]
elsif ary.first.respond_to?(:[]) && target_value.nil?
begin
ary.select { |item| item[property] }
elsif target_value.nil?
ary.select do |item|
item[property]
rescue TypeError
raise_property_error(property)
rescue NoMethodError
return nil unless item.respond_to?(:[])
raise
end
elsif ary.first.respond_to?(:[])
begin
ary.select { |item| item[property] == target_value }
else
ary.select do |item|
item[property] == target_value
rescue TypeError
raise_property_error(property)
rescue NoMethodError
return nil unless item.respond_to?(:[])
raise
end
end
end
Expand All @@ -237,11 +243,14 @@ def uniq(input, property = nil)
ary.uniq
elsif ary.empty? # The next two cases assume a non-empty array.
[]
elsif ary.first.respond_to?(:[])
begin
ary.uniq { |a| a[property] }
else
ary.uniq do |item|
item[property]
rescue TypeError
raise_property_error(property)
rescue NoMethodError
return nil unless item.respond_to?(:[])
raise
end
end
end
Expand Down Expand Up @@ -277,11 +286,14 @@ def compact(input, property = nil)
ary.compact
elsif ary.empty? # The next two cases assume a non-empty array.
[]
elsif ary.first.respond_to?(:[])
begin
ary.reject { |a| a[property].nil? }
else
ary.reject do |item|
item[property].nil?
rescue TypeError
raise_property_error(property)
rescue NoMethodError
return nil unless item.respond_to?(:[])
raise
end
end
end
Expand Down Expand Up @@ -486,10 +498,16 @@ def apply_operation(input, operand, operation)
end

def nil_safe_compare(a, b)
if !a.nil? && !b.nil?
a <=> b
result = a <=> b

if result
result
elsif a.nil?
1
elsif b.nil?
-1
else
a.nil? ? 1 : -1
raise Liquid::ArgumentError, "cannot sort values of incompatible types"
end
end

Expand Down
23 changes: 9 additions & 14 deletions test/integration/standard_filter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ def test_sort_when_property_is_sometimes_missing_puts_nils_last
{ "price" => 1, "handle" => "gamma" },
{ "price" => 2, "handle" => "epsilon" },
{ "price" => 4, "handle" => "alpha" },
{ "handle" => "delta" },
{ "handle" => "beta" },
{ "handle" => "delta" },
]
assert_equal(expectation, @filters.sort(input, "price"))
end
Expand Down Expand Up @@ -852,19 +852,14 @@ def test_all_filters_never_raise_non_liquid_exception
{ 1 => "bar" },
["foo", 123, nil, true, false, Drop, ["foo"], { foo: "bar" }],
]
test_types.each do |first|
test_types.each do |other|
(@filters.methods - Object.methods).each do |method|
arg_count = @filters.method(method).arity
arg_count *= -1 if arg_count < 0
inputs = [first]
inputs << ([other] * (arg_count - 1)) if arg_count > 1
begin
@filters.send(method, *inputs)
rescue Liquid::ArgumentError, Liquid::ZeroDivisionError
nil
end
end
StandardFilters.public_instance_methods(false).each do |method|
arg_count = @filters.method(method).arity
arg_count *= -1 if arg_count < 0

test_types.repeated_permutation(arg_count) do |args|
@filters.send(method, *args)
rescue Liquid::Error
nil
end
end
end
Expand Down

0 comments on commit 0d5e01a

Please sign in to comment.