Skip to content

gh-152849: Fix OverflowError message for out-of-range float timestamps#152850

Open
tonghuaroot wants to merge 4 commits into
python:mainfrom
tonghuaroot:fix-gh-152849-pytime-overflow-msg
Open

gh-152849: Fix OverflowError message for out-of-range float timestamps#152850
tonghuaroot wants to merge 4 commits into
python:mainfrom
tonghuaroot:fix-gh-152849-pytime-overflow-msg

Conversation

@tonghuaroot

@tonghuaroot tonghuaroot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

pytime_from_double() in Python/pytime.c converts a float number of
seconds to a PyTime_t (nanoseconds). On overflow it called
pytime_time_t_overflow(), which reports "timestamp out of range for platform time_t" — but this path never converts to time_t. The integer
path, pytime_from_object(), already reports the same conceptual overflow
with pytime_overflow() ("timestamp too large to convert to C PyTime_t").

This swaps the float path to pytime_overflow() so both paths agree and the
message names the type actually involved. The old wording was wrong in fact,
not only in type: PyTime_t saturates at roughly 292 years (int64
nanoseconds), while 64-bit time_t spans far longer, so e.g.
time.sleep(1e10) (~317 years) overflows PyTime_t yet is well within
time_t range — the reported time_t limit was never the actual constraint.
The correct helper already exists in the same file, so this is a one-line
change that only affects the message text; it targets main only.

User-visible via any float-seconds API, e.g.:

>>> time.sleep(2.0 ** 63)   # before: "... platform time_t"; after: "... C PyTime_t"

Verified in a build of main: the _PyTime_FromSecondsObject() float path
(and time.sleep()) now raises the PyTime_t message for both positive and
negative out-of-range values, matching the integer path; the full
test_time suite passes. A regression test asserting the float-path overflow
message is added to TestCPyTime (fails before the fix, passes after).

…estamps

pytime_from_double() converts a float number of seconds to a PyTime_t
(nanoseconds) but reported overflow with pytime_time_t_overflow()
("out of range for platform time_t"), naming a type it never uses. The
integer path already uses pytime_overflow(); switch the float path to it
so both conversion paths report the same PyTime_t overflow.

@sobolevn sobolevn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(not a full review)

Comment thread Lib/test/test_time.py Outdated
def test_FromSecondsObject_float_overflow_message(self):
# Float path must report a PyTime_t overflow, like the integer path.
from _testinternalcapi import _PyTime_FromSecondsObject
for value in (2.0 ** 63, -(2.0 ** 63)):

@sobolevn sobolevn Jul 2, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you instead use _testcapi.PyTime_MIN and _testcapi.PyTime_MAX please?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, the test now uses float(_testcapi.PyTime_MAX) and float(_testcapi.PyTime_MIN).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in Library.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to Library.

Comment thread Lib/test/test_time.py Outdated
from _testinternalcapi import _PyTime_FromSecondsObject
for value in (2.0 ** 63, -(2.0 ** 63)):
for time_rnd, _ in ROUNDING_MODES:
with self.assertRaisesRegex(OverflowError, "to C PyTime_t"):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please assert the full message.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, it now asserts the full message.

Comment thread Python/pytime.c
@@ -636,7 +636,7 @@ pytime_from_double(PyTime_t *tp, double value, _PyTime_round_t round,

/* See comments in pytime_double_to_denominator */
if (!((double)PyTime_MIN <= d && d < -(double)PyTime_MIN)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message of pytime_overflow currently says "too large," but it can also be too small, let's update to:

timestamp out of range for C PyTime_t

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, updated to timestamp out of range for C PyTime_t. This also covers the too-small case.

Comment thread Lib/test/test_time.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants