gh-152204: Validate date and time fields in _pydatetime.date{time}.fromisoformat - #152205
gh-152204: Validate date and time fields in _pydatetime.date{time}.fromisoformat#152205tonghuaroot wants to merge 8 commits into
_pydatetime.date{time}.fromisoformat#152205Conversation
The pure-Python _parse_isoformat_date read each fixed-width field with int() on a slice, which silently accepts a leading sign or whitespace, or a short slice that runs off the end of the string. Malformed basic-format inputs such as '2020+12' or '2020061' were therefore parsed into a wrong-but-plausible date instead of raising, while the C accelerator rejects them via parse_digits(). Validate that each field slice is exactly N ASCII digits before converting.
serhiy-storchaka
left a comment
There was a problem hiding this comment.
This change has significant impact on performance.
Would not it be simpler to use .isascii() at the beginning and .isdigit() for each fragment?
|
Done in 46f6881: one |
|
Done in a025467: moved the reader to a module-level |
|
There are conflicts now. |
|
Done in aed8e2d: merged main (conflicts resolved) and removed the duplicate 7-char cases. |
serhiy-storchaka
left a comment
There was a problem hiding this comment.
Replace this with more efficient .isacii() and .isdigits() checks.
…op the redundant length check, and add per-component tests
|
Done in 154340c: re-merged main (restores the dropped tests), the fraction now uses |
StanFromIreland
left a comment
There was a problem hiding this comment.
One little nit, otherwise LGTM.
This will unfortunately introduce a bit of a perf hit, although it's fine as anyone looking for performance should be using the C accelerator anyway.
_pydatetime.date{time}.fromisoformat
_pydatetime._parse_isoformat_datereads each fixed-width field withint()on a slice, without checking that the slice is exactly N ASCII digits.int()accepts a leading+/-/whitespace and a short string, so several malformed ISO 8601 basic-format dates are silently parsed into a wrong-but-plausibledateinstead of raisingValueError:The C accelerator rejects all of these via
parse_digits()(which requires the exact field width and digit-only content), so this is a C-vs-pure-Python divergence. The pure-Python path is used when the_datetimeC extension is unavailable, and directly via_pydatetime.This validates each field slice (
year/month/day/weekno/weekday) to be exactly N ASCII digits before converting, mirroring the Cparse_digits(), and extendsdatetimetester'stest_fromisoformat_failswith the affected inputs (the new cases now reject on both implementations).Fixes #152204.
Prepared with AI assistance (Claude Code) and verified by hand against a debug build, against both the C and pure-Python implementations.
date.fromisoformatsilently mis-parses malformed basic-format dates #152204