Skip to content

Commit 7e9fbaf

Browse files
time: make parse_rfc3339 accept t, and space, in addition to T, reject incomplete date-times and such with no timezone (fix #25272) (#25316)
1 parent 563987c commit 7e9fbaf

3 files changed

Lines changed: 26 additions & 16 deletions

File tree

‎vlib/time/parse.c.v‎

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,18 +158,16 @@ pub fn parse_rfc3339(s string) !Time {
158158

159159
if is_date {
160160
year, month, day = check_and_extract_date(s)!
161-
if s.len == date_format_buffer.len {
162-
return new(Time{
163-
year: year
164-
month: month
165-
day: day
166-
is_local: false
167-
})
168-
}
161+
}
162+
if s.len <= date_format_buffer.len {
163+
return error('date-time too short to parse')
164+
}
165+
if s[10] !in [u8(`T`), `t`, ` `] {
166+
return error('invalid date-time separator:${s[10].ascii_str()}')
169167
}
170168

171169
is_datetime := if s.len >= date_format_buffer.len + 1 + time_format_buffer.len + 1 {
172-
is_date && s[10] == u8(`T`)
170+
is_date
173171
} else {
174172
false
175173
}
@@ -189,7 +187,7 @@ pub fn parse_rfc3339(s string) !Time {
189187
timezone_start_position++
190188
if timezone_start_position == s.len {
191189
return error('timezone error: expected "Z" or "z" or "+" or "-" in position ${timezone_start_position}, not "${[
192-
s[timezone_start_position],
190+
s[s.len - 1],
193191
].bytestr()}"')
194192
}
195193
}

‎vlib/time/parse_test.v‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ fn test_parse_rfc3339() {
196196
['2024-10-19T22:47:08.9+00:00', '2024-10-19 22:47:08.900000'],
197197
['2024-10-20T01:47:08+03:00', '2024-10-19 22:47:08.000000'],
198198
['2024-10-20T01:47:08.981+03:00', '2024-10-19 22:47:08.981000'],
199+
['1979-05-27t07:32:00z', '1979-05-27 07:32:00.000000'],
200+
['1979-05-27 07:32:00Z', '1979-05-27 07:32:00.000000'],
201+
['1979-05-27T00:32:00.999999Z', '1979-05-27 00:32:00.999999'],
199202
]
200203
for pair in pairs {
201204
input, expected := pair[0], pair[1]
@@ -208,18 +211,23 @@ fn test_parse_rfc3339() {
208211
}
209212
assert invalid_rfc3339('22:47:08Z') == 'missing date part of RFC 3339'
210213
assert invalid_rfc3339('01:47:08.981+03:00') == 'missing date part of RFC 3339'
211-
assert invalid_rfc3339('2006-01-00') == 'date error: invalid day 0'
212-
assert invalid_rfc3339('2006-01-32') == 'date error: invalid day 32'
213-
assert invalid_rfc3339('2006-01-88') == 'date error: invalid day 88'
214-
assert invalid_rfc3339('2006-00-01') == 'date error: invalid month 0'
215-
assert invalid_rfc3339('2006-13-01') == 'date error: invalid month 13'
216-
assert invalid_rfc3339('2006-77-01') == 'date error: invalid month 77'
214+
assert invalid_rfc3339('2006-01-00T00:00:00Z') == 'date error: invalid day 0'
215+
assert invalid_rfc3339('2006-01-32T00:00:00Z') == 'date error: invalid day 32'
216+
assert invalid_rfc3339('2006-01-88T00:00:00Z') == 'date error: invalid day 88'
217+
assert invalid_rfc3339('2006-00-01T00:00:00Z') == 'date error: invalid month 0'
218+
assert invalid_rfc3339('2006-13-01T00:00:00Z') == 'date error: invalid month 13'
219+
assert invalid_rfc3339('2006-77-01T00:00:00Z') == 'date error: invalid month 77'
217220
assert invalid_rfc3339('2006-01-01T24:47:08Z') == 'invalid hour: 24'
218221
assert invalid_rfc3339('2006-01-01T99:47:08Z') == 'invalid hour: 99'
219222
assert invalid_rfc3339('2006-01-01T23:60:08Z') == 'invalid minute: 60'
220223
assert invalid_rfc3339('2006-01-01T23:99:08Z') == 'invalid minute: 99'
221224
assert invalid_rfc3339('2006-01-01T23:59:60Z') == 'invalid second: 60'
222225
assert invalid_rfc3339('2006-01-01T23:59:99Z') == 'invalid second: 99'
226+
assert invalid_rfc3339('1979-05-27X07:32:00Z') == 'invalid date-time separator:X'
227+
assert invalid_rfc3339('1979-05-27T07:32:00') == 'timezone error: datetime string is too short'
228+
assert invalid_rfc3339('1979-05-27') == 'date-time too short to parse'
229+
assert invalid_rfc3339('1979-05-27T00:32:00.999999') == 'timezone error: expected "Z" or "z" or "+" or "-" in position 26, not "9"'
230+
assert invalid_rfc3339('1979-05-27T00:32:00.') == 'timezone error: expected "Z" or "z" at the end of the string'
223231
}
224232

225233
fn test_ad_second_to_parse_result_in_2001() {

‎vlib/toml/checker/checker.v‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ fn toml_parse_time(s string) !time.Time {
2222
// complete the partial time, with an arbitrary date:
2323
return time.parse_rfc3339('0001-01-01T' + s)
2424
}
25+
if s.len == 10 {
26+
// complete the partial date, with zero time and zero timezone
27+
return time.parse_rfc3339(s + 'T00:00:00Z')
28+
}
2529
return time.parse_rfc3339(s)!
2630
}
2731

0 commit comments

Comments
 (0)