Skip to content

Commit

Permalink
Handle too long dates passed to DateTime.parse
Browse files Browse the repository at this point in the history
This raises an ArgumentError with a different message from the invalid
date message since Ruby 3.0.3 when the string passed is too long, as a
mitigation for CVE-2021-41817.
https://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/

In this case we should just return nil, like when the date itself is
invalid.
  • Loading branch information
rosa committed Dec 20, 2021
1 parent 6e5db59 commit 96202c9
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 19 deletions.
44 changes: 25 additions & 19 deletions lib/mail/fields/common_date_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,32 @@

module Mail
class CommonDateField < NamedStructuredField #:nodoc:
def self.singular?
true
end
class << self
def singular?
true
end

def self.normalize_datetime(string)
if Utilities.blank?(string)
datetime = ::DateTime.now
else
stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
begin
datetime = ::DateTime.parse(stripped)
rescue ArgumentError => e
raise unless 'invalid date' == e.message
def normalize_datetime(string)
if Utilities.blank?(string)
datetime = ::DateTime.now
else
stripped = string.to_s.gsub(/\(.*?\)/, '').squeeze(' ')
with_invalid_date_time_error_handling do
datetime = ::DateTime.parse(stripped)
end
end

if datetime
datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
else
string
end
end

if datetime
datetime.strftime('%a, %d %b %Y %H:%M:%S %z')
else
string
def with_invalid_date_time_error_handling(&block)
yield
rescue ArgumentError => e
raise unless e.message =~ /\A(invalid date|string length \(\d+\) exceeds the limit \d+)\z/
end
end

Expand All @@ -33,9 +39,9 @@ def initialize(value = nil, charset = nil)

# Returns a date time object of the parsed date
def date_time
::DateTime.parse("#{element.date_string} #{element.time_string}")
rescue ArgumentError => e
raise e unless e.message == 'invalid date'
self.class.with_invalid_date_time_error_handling do
::DateTime.parse("#{element.date_string} #{element.time_string}")
end
end

def default
Expand Down
6 changes: 6 additions & 0 deletions spec/mail/fields/date_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,11 @@
field = Mail::DateField.new("12 Aug 2009 30:00:02 GMT")
expect(field.date_time).to be_nil
end

it "should handle too long invalid date" do
# field = Mail::DateField.new("12 Aug 2009 30:00:02 GMT")
field = Mail::DateField.new("Wed, 23 Jan 2019 30:51:32 -0500")
expect(field.date_time).to be_nil
end
end
end

0 comments on commit 96202c9

Please sign in to comment.