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

time: better handling of overflow in time.Time #71979

Open
neild opened this issue Feb 26, 2025 · 6 comments
Open

time: better handling of overflow in time.Time #71979

neild opened this issue Feb 26, 2025 · 6 comments
Labels
LibraryProposal Issues describing a requested change to the Go standard library or x/ libraries, but not to a tool NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.

Comments

@neild
Copy link
Contributor

neild commented Feb 26, 2025

The time.Time type has a large, but finite range. The time package does not, so far as I can determine, document what this range is.

A Time can represent instants billions of years in the past or future. So far as I can tell, we've taken a general attitude that instants outside the probable lifespan of the human species are out of scope for the package and can be ignored.

For example, time.Unix converts a Unix timestamp (seconds & nanoseconds since the Unix epoch) to a Time. It documents the handling of out-of-range values only by saying:

Not all sec values have a corresponding time value. One such value is 1<<63-1 (the largest int64 value).

Functions such as time.AddDate do not document their behavior on overflow.

Most programs will never encounter out-of-range dates. (If Go proves to be unexpectedly durable on geologic time scales, we can leave the problem of increasing the size of the time.Time seconds counter to future generations.) However, a program handling adversarial inputs (such as a very large Unix timestamp) may be induced to overflow a time.Time, with surprising and undocumented results.

We could harden the time package a bit more against overflow. Some specific functions that we might harden:

  • time.Unix could either saturate or return the zero time when provided with an out-of-range value.
  • time.Add and time.AddDate could saturate rather than wrapping on overflow.
  • time.Round could either truncate or saturate on overflow.

There might be others I'm missing.

Alternatively, we could leave the implementation alone and document what validation users should perform to adequately defend against adversarial inputs to time.Unix.

@gabyhelp gabyhelp added the LibraryProposal Issues describing a requested change to the Go standard library or x/ libraries, but not to a tool label Feb 26, 2025
@seankhliao
Copy link
Member

In #63844 it was noted that restricting to ±32767 years wasn't really acceptable

@neild
Copy link
Contributor Author

neild commented Feb 26, 2025

If it isn't clear, this issue isn't about changing the range of supported instants. It's about what we do when some time package operation goes outside that range.

@seankhliao
Copy link
Member

I think it does point to needing to support a range outside the probable lifespan of the human species...

there's #64514 for underflow, #56909 and #20678 for overflow, perhaps we should merge these?

@seankhliao seankhliao added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 26, 2025
@dsnet
Copy link
Member

dsnet commented Feb 27, 2025

Personally, I would expect to overflow to use saturation arithmetic. It's what I've observed for time.Time.Sub and I guess I had mistakenly assumed was true for all other arithmetic methods. I've relied on the implicit saturation handling of Sub quite a bit.

Do you have any suggestions for time.Duration where you use the native Go + and - operation, which will overflow according to typical two's complement arithmentic? Should there be a Add method to add with saturation?

@neild
Copy link
Contributor Author

neild commented Feb 27, 2025

time.Duration is an int64, and the fact that it's an int64 is user-visible, so the overflow behavior there is at least predictable. time.Time, in contrast, doesn't define what its valid range is and has no documented way to detect or handle overflow. (What happens if you call time.Unix with an out-of-range value? What values are out-of-range? We don't say. Maybe the answer is "don't create times more than a billion years away from the present", but if so, we should actually document that.)

Maybe there should be a saturating Duration.Add, but I think that's out of scope for this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LibraryProposal Issues describing a requested change to the Go standard library or x/ libraries, but not to a tool NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

4 participants