early match number expressions with Regex

This commit is contained in:
Michael Go
2025-01-07 14:32:46 -04:00
parent 7c592c1c00
commit cef64e277e
+19 -9
View File
@@ -69,6 +69,9 @@ module Liquid
# Use an atomic group (?>...) to avoid pathological backtracing from # Use an atomic group (?>...) to avoid pathological backtracing from
# malicious input as described in https://github.com/Shopify/liquid/issues/1357 # malicious input as described in https://github.com/Shopify/liquid/issues/1357
RANGES_REGEX = /\A\(\s*(?>(\S+)\s*\.\.)\s*(\S+)\s*\)\z/ RANGES_REGEX = /\A\(\s*(?>(\S+)\s*\.\.)\s*(\S+)\s*\)\z/
INTEGER_REGEX = /\A(-?\d+)\z/
FLOAT_REGEX = /\A(-?\d+)\.\d+\z/
CACHE = LruRedux::Cache.new(10_000) # most themes would have less than 2,000 unique expression CACHE = LruRedux::Cache.new(10_000) # most themes would have less than 2,000 unique expression
class << self class << self
@@ -112,8 +115,16 @@ module Liquid
return false if byte != DASH && byte != DOT && (byte < ZERO || byte > NINE) return false if byte != DASH && byte != DOT && (byte < ZERO || byte > NINE)
is_integer = true # check if the markup is simple integer or float
last_dot_pos = nil case markup
when INTEGER_REGEX
return markup.to_i
when FLOAT_REGEX
return markup.to_f
end
# The markup could be a float with multiple dots
first_dot_pos = nil
num_end_pos = nil num_end_pos = nil
while (byte = ss.scan_byte) while (byte = ss.scan_byte)
@@ -123,24 +134,23 @@ module Liquid
next if num_end_pos next if num_end_pos
if byte == DOT if byte == DOT
if is_integer == false if first_dot_pos.nil?
num_end_pos = ss.pos - 1 first_dot_pos = ss.pos
else else
is_integer = false # we found another dot, so we know that the number ends here
last_dot_pos = ss.pos num_end_pos = ss.pos - 1
end end
end end
end end
num_end_pos = markup.length if ss.eos? num_end_pos = markup.length if ss.eos?
return markup.to_i if is_integer
if num_end_pos if num_end_pos
# number ends with a number "123.123" # number ends with a number "123.123"
markup.byteslice(0, num_end_pos).to_f markup.byteslice(0, num_end_pos).to_f
else else
markup.byteslice(0, last_dot_pos).to_f # number ends with a dot "123."
markup.byteslice(0, first_dot_pos).to_f
end end
end end
end end