gh-154892: Fix PyLong_AsLong() error checks in _zoneinfo - #154901
gh-154892: Fix PyLong_AsLong() error checks in _zoneinfo#154901BHUVANSH855 wants to merge 4 commits into
Conversation
| @@ -2311,7 +2311,7 @@ get_local_timestamp(PyObject *dt, int64_t *local_ts) | |||
| } | |||
| hour = PyLong_AsLong(num); | |||
There was a problem hiding this comment.
Not exactly the issue, but related. What if a subclass returns 2**40? Maybe PyLong_AsInt can be used.
There was a problem hiding this comment.
That's a good point. I hadn't considered oversized integer values like 2**40. Since this PR is focused on fixing the -1 sentinel handling from PyLong_AsLong(), I'd prefer to keep that as a separate change if we decide PyLong_AsInt() is the better choice.
There was a problem hiding this comment.
Ok. Could you open an issue for this so we do not forget?
There was a problem hiding this comment.
Sure, I'll investigate this further and open a separate issue to track it so it doesn't get lost.
There was a problem hiding this comment.
Thanks for pointing this out! I investigated it further.
The C implementation currently uses PyObject_GetAttrString() + PyLong_AsLong() for datetime subclasses, but the pure Python implementation follows the same approach:
(dt.toordinal() - EPOCHORDINAL) * 86400 + dt.hour * 3600 + dt.minute * 60 + dt.secondSo both implementations intentionally consult the subclass-visible hour, minute, and second attributes.
I also tested subclasses returning very large values (e.g. 10**12), and both the C and pure Python implementations behave the same way. This means switching to PyLong_AsInt() in the C implementation would only narrow the accepted range there, while the pure Python implementation would continue to accept arbitrarily large values, resulting in inconsistent behavior between the two implementations.
It seems the underlying question is whether ZoneInfo should be consulting overridden subclass attributes at all, rather than whether PyLong_AsLong() should be replaced with PyLong_AsInt().
|
I'll change "Closes: gh-154892" in your PR description to "Closes issue gh-154892", because the use of "closes" keyword would close the issue immediately after this PR is merged and before 3 other backport PRs of your change to our maintenance branches are merged. We want to close the issue after the backport PRs are merged. |
Summary
Fix
Modules/_zoneinfo.c:get_local_timestamp()to correctly distinguish a legitimate-1result fromPyLong_AsLong()from an actual conversion error by checkingPyErr_Occurred(), matching the documented C API behavior and the pure-Python implementation.The previous implementation treated any
-1return value fromPyLong_AsLong()as an error, even when no exception was set. This causeddatetimesubclasses overridinghour,minute, orsecondto return-1to incorrectly raise an exception in the C accelerator.This PR also adds a regression test covering
datetimesubclasses whosehour,minute, andsecondproperties return-1.Issue
Closes issue gh-154892