Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback for situations where Python's fromtimestamp() raises OSError or OverflowError #2972

Merged
merged 5 commits into from
Jun 26, 2023

Conversation

jonemo
Copy link
Contributor

@jonemo jonemo commented Jun 18, 2023

This addresses various issues where calling datetime.datetime.fromtimestamp() fails with OverflowError or OSError. These behaviors are platform-dependent and currently seem to affect mainly Windows. The Python documentation mentions the existence of these failure mode.

This PR adds a fallback for when parsing a numeric timestamp fails that uses timedelta to create a datetime that is offset from the epoch (Jan 1, 1970) by the given number of seconds. This has the same effect as calling fromtimestamp() without calling the C localtime() function.

Some related issues:

The general theme of these issues is that a service returns a timestamp that falls outside the timespan between 1970 and 2038. Examples I have seen include Quicksight dashboards with time axes starting in the early 1900s, ACM certificates that expire after 2038, and SSM Patches with incorrect InstalledTime fields claiming patch dates before 1970.

#1970 and #1939 have been previous attempts to address a subset of these problems. The former has not been merged, the solution from the latter remains in place after this PR. (An aside: Note the coincidence that PR ID 1970 addresses an issue related to epoch times!)

Q: Why not also replace the use of fromtimestamp() in credentials.py?

A: In order to preserve existing code paths, this new fallback is not implemented as a drop-in replacement for Python's fromtimestamp. As a result, I could not use it to also replace the one remaining use of fromtimestamp() in credentials.py. That's also why I made _epoch_seconds_to_datetime private (with leading _). This remaining instance of fromtimestamp() is unlikely to yield the exceptions addressed in this PR because timestamps in credentials do not fall outside the "safe" timespan between 1970 and 2038 (currently and in the foreseeable future).

@jonemo jonemo requested a review from nateprewitt June 18, 2023 22:03
@codecov-commenter
Copy link

codecov-commenter commented Jun 18, 2023

Codecov Report

Patch coverage: 88.23% and project coverage change: -0.01 ⚠️

Comparison is base (bc89f15) 93.29% compared to head (768b88a) 93.28%.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2972      +/-   ##
===========================================
- Coverage    93.29%   93.28%   -0.01%     
===========================================
  Files           64       64              
  Lines        13592    13607      +15     
===========================================
+ Hits         12680    12693      +13     
- Misses         912      914       +2     
Impacted Files Coverage Δ
botocore/utils.py 79.42% <88.23%> (+0.06%) ⬆️

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

{
"type": "bugfix",
"category": "Parsers",
"description": "fixes `#3642 <https://github.com/boto/botocore/issues/3642>`__, `#2564 <https://github.com/boto/botocore/issues/2564>`__, `#2355 <https://github.com/boto/botocore/issues/2355>`__, `#1783 <https://github.com/boto/botocore/issues/1783>`__, boto/boto3`#2069 <https://github.com/boto/botocore/issues/2069>`__"
Copy link
Contributor

Choose a reason for hiding this comment

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

We can link to an issue, but ideally the description should be mostly explanatory.

e.g.

Fixes datetime parse error handling for 32-bit systems and UTC positive timezone offsets

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, after expansion those issue references are a bit excessive! Fixed in 768b88a.

Copy link
Contributor

@nateprewitt nateprewitt left a comment

Choose a reason for hiding this comment

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

Looks good, thanks @jonemo!

@jonemo jonemo merged commit 7e4de85 into boto:develop Jun 26, 2023
@jonemo jonemo deleted the fix-negative-timestamps branch June 26, 2023 23:54
aws-sdk-python-automation added a commit that referenced this pull request Jun 27, 2023
* release-1.29.162:
  Bumping version to 1.29.162
  Update to latest models
  Revert "User Agent 2.0 (#2955)" (#2976)
  User Agent 2.0 (#2955)
  remove leftover print() statement (#2975)
  Fallback for situations where Python's fromtimestamp() raises OSError or OverflowError (#2972)
@akx
Copy link
Contributor

akx commented Nov 15, 2023

It looks like the docstring in _epoch_seconds_to_datetime is at odds with what it does:

into a datetime.datetime in UTC

yet it accepts an arbitrary tzinfo argument (which ends up being tzlocal or tzwinlocal) when called from parse_timestamp, the only caller?

Secondly: _parse_timestamp_with_tzinfo, which is called before we get to the bit that could call _epoch_seconds_to_datetime, already attempts to do timestamp parsing; shouldn't this logic be there?

(I know I'm very late with this review sort of thing, but I'm looking at making botocore a little faster around timestamp handling because it's actually bit of a bottleneck.)

EDIT: See #3063.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants