@@ -355,27 +355,30 @@ def _find_isoformat_datetime_separator(dtstr):
355355 return 8
356356
357357
358+ def _read_isoformat_component (s , n ):
359+ # The caller has verified the string is ASCII, so isdigit() matches only
360+ # the ASCII digits accepted by the C parser.
361+ if len (s ) != n or not s .isdigit ():
362+ raise ValueError ("Invalid isoformat string" )
363+ return int (s )
364+
365+
358366def _parse_isoformat_date (dtstr ):
359367 # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,
360368 # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
361369 if len (dtstr ) not in (7 , 8 , 10 ):
362370 raise ValueError ("Invalid isoformat string" )
363371 if not dtstr .isascii ():
364- raise ValueError (f"Invalid isoformat string: { dtstr !r} " )
365- def _read (s , n ):
366- # dtstr is ASCII, so isdigit() matches only ASCII digits.
367- if len (s ) != n or not s .isdigit ():
368- raise ValueError (f"Invalid isoformat string: { dtstr !r} " )
369- return int (s )
370-
371- year = _read (dtstr [0 :4 ], 4 )
372+ raise ValueError ("Invalid isoformat string" )
373+
374+ year = _read_isoformat_component (dtstr [0 :4 ], 4 )
372375 has_sep = dtstr [4 ] == '-'
373376
374377 pos = 4 + has_sep
375378 if dtstr [pos :pos + 1 ] == "W" :
376379 # YYYY-?Www-?D?
377380 pos += 1
378- weekno = _read (dtstr [pos :pos + 2 ], 2 )
381+ weekno = _read_isoformat_component (dtstr [pos :pos + 2 ], 2 )
379382 pos += 2
380383
381384 dayno = 1
@@ -385,17 +388,17 @@ def _read(s, n):
385388
386389 pos += has_sep
387390
388- dayno = _read (dtstr [pos :pos + 1 ], 1 )
391+ dayno = _read_isoformat_component (dtstr [pos :pos + 1 ], 1 )
389392
390393 return list (_isoweek_to_gregorian (year , weekno , dayno ))
391394 else :
392- month = _read (dtstr [pos :pos + 2 ], 2 )
395+ month = _read_isoformat_component (dtstr [pos :pos + 2 ], 2 )
393396 pos += 2
394397 if (dtstr [pos :pos + 1 ] == "-" ) != has_sep :
395398 raise ValueError ("Inconsistent use of dash separator" )
396399
397400 pos += has_sep
398- day = _read (dtstr [pos :pos + 2 ], 2 )
401+ day = _read_isoformat_component (dtstr [pos :pos + 2 ], 2 )
399402
400403 return [year , month , day ]
401404
@@ -413,7 +416,7 @@ def _parse_hh_mm_ss_ff(tstr):
413416 if (len_str - pos ) < 2 :
414417 raise ValueError ("Incomplete time component" )
415418
416- time_comps [comp ] = int (tstr [pos :pos + 2 ])
419+ time_comps [comp ] = _read_isoformat_component (tstr [pos :pos + 2 ], 2 )
417420
418421 pos += 2
419422 next_char = tstr [pos :pos + 1 ]
@@ -455,6 +458,8 @@ def _parse_isoformat_time(tstr):
455458 len_str = len (tstr )
456459 if len_str < 2 :
457460 raise ValueError ("Isoformat time too short" )
461+ if not tstr .isascii ():
462+ raise ValueError ("Invalid isoformat string" )
458463
459464 # This is equivalent to re.search('[+-Z]', tstr), but faster
460465 tz_pos = (tstr .find ('-' ) + 1 or tstr .find ('+' ) + 1 or tstr .find ('Z' ) + 1 )
0 commit comments