diff --git a/History.md b/History.md index a3a62052..935151bc 100644 --- a/History.md +++ b/History.md @@ -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 diff --git a/lib/liquid/standardfilters.rb b/lib/liquid/standardfilters.rb index e7cb5c38..98e38f5f 100644 --- a/lib/liquid/standardfilters.rb +++ b/lib/liquid/standardfilters.rb @@ -213,17 +213,23 @@ module Liquid 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 @@ -237,11 +243,14 @@ module Liquid 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 @@ -277,11 +286,14 @@ module Liquid 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 @@ -486,10 +498,16 @@ module Liquid 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 diff --git a/test/integration/standard_filter_test.rb b/test/integration/standard_filter_test.rb index f80d7ad0..e7b34c16 100644 --- a/test/integration/standard_filter_test.rb +++ b/test/integration/standard_filter_test.rb @@ -259,8 +259,8 @@ class StandardFiltersTest < Minitest::Test { "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 @@ -852,19 +852,14 @@ class StandardFiltersTest < Minitest::Test { 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