From d5f7ec9ee0cb66d1a3bdd16616feaa20b84d8122 Mon Sep 17 00:00:00 2001 From: Xingang Huang Date: Tue, 23 Jun 2026 15:12:04 -0500 Subject: [PATCH] SRCH-694 return parser error for oversized days --- CHANGELOG.md | 3 +++ VERSION | 2 +- lib/sparkql/parser_tools.rb | 40 +++++++++++++++++++++++++++++-------- test/unit/parser_test.rb | 12 +++++++++++ 4 files changed, 48 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9d75b4..fc0cc09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +v1.3.6, 2026-06-23 + * [BUGFIX] Parser crash when days()/weekdays() exceed max offset + v1.3.5, 2026-04-30 * [IMPROVEMENT] add date_date() function diff --git a/VERSION b/VERSION index 80e78df..95b25ae 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.5 +1.3.6 diff --git a/lib/sparkql/parser_tools.rb b/lib/sparkql/parser_tools.rb index b0ec9d4..54ba548 100644 --- a/lib/sparkql/parser_tools.rb +++ b/lib/sparkql/parser_tools.rb @@ -171,6 +171,16 @@ def tokenize_literal_negation(number_token) end def tokenize_multiple(lit1, lit2) + if lit1.nil? || lit2.nil? + return nil if errors? + + tokenizer_error(token: @lexer.last_field, + message: 'Invalid value in field list.', + status: :fatal, + syntax: true) + return nil + end + final_type = lit1[:type] if lit1[:type] != lit2[:type] final_type = coercible_types(lit1[:type], lit2[:type]) @@ -224,15 +234,17 @@ def tokenize_function(name, f_args) resolver = function_resolver(name, args) resolver.validate if resolver.errors? - tokenizer_error(token: @lexer.last_field, - message: "Error parsing function #{resolver.errors.join(',')}", - status: :fatal, - syntax: true) - nil - else - result = resolver.call - result.nil? ? result : result.merge(condition: "#{name}(#{condition_list.join(',')})") + report_function_resolver_errors(resolver) + return nil end + + result = resolver.call + if result.nil? + report_function_resolver_errors(resolver) if resolver.errors? + return nil + end + + result.merge(condition: "#{name}(#{condition_list.join(',')})") end def tokenize_arithmetic(lhs, operator, rhs) @@ -448,4 +460,16 @@ def current_timestamp def offset @offset ||= current_timestamp.strftime('%:z') end + + private + + def report_function_resolver_errors(resolver) + resolver.errors.each do |error| + tokenizer_error(token: error.token || @lexer.last_field, + message: error.message, + status: error.status, + syntax: error.syntax?, + constraint: error.constraint?) + end + end end diff --git a/test/unit/parser_test.rb b/test/unit/parser_test.rb index c7304bd..4d51a84 100644 --- a/test/unit/parser_test.rb +++ b/test/unit/parser_test.rb @@ -1232,6 +1232,18 @@ def test_cast_with_invalid_type assert_equal 0, expressions.last[:block_group] end + test 'oversized days() in Bt range returns parser error instead of raising' do + [ + 'OriginalEntryTimestamp Bt days(0),days(365001)', + 'OpenHouses Bt days(0),days(9223372036854775807)' + ].each do |filter| + @parser = Parser.new + assert_nothing_raised { @parser.parse(filter) } + assert @parser.fatal_errors?, "Expected fatal error for #{filter}" + assert_match(/max offset/i, @parser.errors.first.message) + end + end + private def parser_errors(filter)