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

Add support for pre-unix-epoch file dates on Apple platforms (#108277) #117451

Merged
merged 1 commit into from Nov 1, 2023

Conversation

Byron
Copy link
Member

@Byron Byron commented Oct 31, 2023

Please note that even though the assertion being hit is the same on MacOS and thus similar to what's described in #108277, on MacOS it's possible to convert the numbers such that they are valid, don't hit the assertion and are round-trippable.
Doing so effectively fixes the issue on Apple platforms.

This PR does not attempt to harden other platforms against negative nanoseconds, which can happen for many reasons including mild filesystem corruption.


Time in UNIX system calls counts from the epoch, 1970-01-01. The timespec
struct used in various system calls represents this as a number of seconds and
a number of nanoseconds. Nanoseconds are required to be between 0 and
999_999_999, because the portion outside that range should be represented in
the seconds field; if nanoseconds were larger than 999_999_999, the seconds
field should go up instead.

Suppose you ask for the time 1969-12-31, what time is that? On UNIX systems
that support times before the epoch, that's seconds=-86400, one day before the
epoch. But now, suppose you ask for the time 1969-12-31 23:59:00.1. In other
words, a tenth of a second after one minute before the epoch. On most UNIX
systems, that's represented as seconds=-60, nanoseconds=100_000_000. The macOS
bug is that it returns seconds=-59, nanoseconds=-900_000_000.

While that's in some sense an accurate description of the time (59.9 seconds
before the epoch), that violates the invariant of the timespec data structure:
nanoseconds must be between 0 and 999999999. This causes this assertion in the
Rust standard library.

So, on macOS, if we get a Timespec value with seconds less than or equal to
zero, and nanoseconds between -999_999_999 and -1 (inclusive), we can add
1_000_000_000 to the nanoseconds and subtract 1 from the seconds, and then
convert. The resulting timespec value is still accepted by macOS, and when fed
back into the OS, produces the same results. (If you set a file's mtime with
that timestamp, then read it back, you get back the one with negative
nanoseconds again.)

Co-authored-by: Josh Triplett josh@joshtriplett.org

@rustbot
Copy link
Collaborator

rustbot commented Oct 31, 2023

r? @joshtriplett

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added O-unix Operating system: Unix-like S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Oct 31, 2023
…ng#108277)

Time in UNIX system calls counts from the epoch, 1970-01-01. The timespec
struct used in various system calls represents this as a number of seconds and
a number of nanoseconds. Nanoseconds are required to be between 0 and
999_999_999, because the portion outside that range should be represented in
the seconds field; if nanoseconds were larger than 999_999_999, the seconds
field should go up instead.

Suppose you ask for the time 1969-12-31, what time is that? On UNIX systems
that support times before the epoch, that's seconds=-86400, one day before the
epoch. But now, suppose you ask for the time 1969-12-31 23:59:00.1. In other
words, a tenth of a second after one minute before the epoch.  On most UNIX
systems, that's represented as seconds=-60, nanoseconds=100_000_000. The macOS
bug is that it returns seconds=-59, nanoseconds=-900_000_000.

While that's in some sense an accurate description of the time (59.9 seconds
before the epoch), that violates the invariant of the timespec data structure:
nanoseconds must be between 0 and 999999999. This causes this assertion in the
Rust standard library.

So, on macOS, if we get a Timespec value with seconds less than or equal to
zero, and nanoseconds between -999_999_999 and -1 (inclusive), we can add
1_000_000_000 to the nanoseconds and subtract 1 from the seconds, and then
convert.  The resulting timespec value is still accepted by macOS, and when fed
back into the OS, produces the same results. (If you set a file's mtime with
that timestamp, then read it back, you get back the one with negative
nanoseconds again.)

Co-authored-by: Josh Triplett <josh@joshtriplett.org>
@joshtriplett
Copy link
Member

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Oct 31, 2023

📌 Commit a8ece11 has been approved by joshtriplett

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 31, 2023
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 31, 2023
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#113241 (rustdoc: Document lack of object safety on affected traits)
 - rust-lang#117388 (Turn const_caller_location from a query to a hook)
 - rust-lang#117417 (Add a stable MIR visitor)
 - rust-lang#117439 (prepopulate opaque ty storage before using it)
 - rust-lang#117451 (Add support for pre-unix-epoch file dates on Apple platforms (rust-lang#108277))

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 31, 2023
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#113241 (rustdoc: Document lack of object safety on affected traits)
 - rust-lang#117388 (Turn const_caller_location from a query to a hook)
 - rust-lang#117417 (Add a stable MIR visitor)
 - rust-lang#117439 (prepopulate opaque ty storage before using it)
 - rust-lang#117451 (Add support for pre-unix-epoch file dates on Apple platforms (rust-lang#108277))

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit d06200b into rust-lang:master Nov 1, 2023
11 checks passed
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Nov 1, 2023
Rollup merge of rust-lang#117451 - Byron:issue-108277-apple-fix, r=joshtriplett

Add support for pre-unix-epoch file dates on Apple platforms (rust-lang#108277)

Please note that even though the assertion being hit is the same on MacOS and thus similar to what's described in rust-lang#108277, on MacOS it's possible to convert the numbers such that they are valid, don't hit the assertion and are round-trippable.
Doing so effectively fixes the issue on Apple platforms.

This PR does not attempt to harden other platforms against negative nanoseconds, which can happen for many reasons including mild filesystem corruption.

----

Time in UNIX system calls counts from the epoch, 1970-01-01. The timespec
struct used in various system calls represents this as a number of seconds and
a number of nanoseconds. Nanoseconds are required to be between 0 and
999_999_999, because the portion outside that range should be represented in
the seconds field; if nanoseconds were larger than 999_999_999, the seconds
field should go up instead.

Suppose you ask for the time 1969-12-31, what time is that? On UNIX systems
that support times before the epoch, that's seconds=-86400, one day before the
epoch. But now, suppose you ask for the time 1969-12-31 23:59:00.1. In other
words, a tenth of a second after one minute before the epoch.  On most UNIX
systems, that's represented as seconds=-60, nanoseconds=100_000_000. The macOS
bug is that it returns seconds=-59, nanoseconds=-900_000_000.

While that's in some sense an accurate description of the time (59.9 seconds
before the epoch), that violates the invariant of the timespec data structure:
nanoseconds must be between 0 and 999999999. This causes this assertion in the
Rust standard library.

So, on macOS, if we get a Timespec value with seconds less than or equal to
zero, and nanoseconds between -999_999_999 and -1 (inclusive), we can add
1_000_000_000 to the nanoseconds and subtract 1 from the seconds, and then
convert.  The resulting timespec value is still accepted by macOS, and when fed
back into the OS, produces the same results. (If you set a file's mtime with
that timestamp, then read it back, you get back the one with negative
nanoseconds again.)

Co-authored-by: Josh Triplett <josh@joshtriplett.org>
@rustbot rustbot added this to the 1.75.0 milestone Nov 1, 2023
@Byron Byron deleted the issue-108277-apple-fix branch November 1, 2023 06:15
bors-ferrocene bot added a commit to ferrocene/ferrocene that referenced this pull request Nov 1, 2023
78: Automated pull from upstream `master` r=tshepang a=github-actions[bot]


This PR pulls the following changes from the upstream repository:

* rust-lang/rust#113970
* rust-lang/rust#117459
  * rust-lang/rust#117451
  * rust-lang/rust#117439
  * rust-lang/rust#117417
  * rust-lang/rust#117388
  * rust-lang/rust#113241
* rust-lang/rust#117462
* rust-lang/rust#117450
* rust-lang/rust#117407
* rust-lang/rust#117444
  * rust-lang/rust#117438
  * rust-lang/rust#117421
  * rust-lang/rust#117416
  * rust-lang/rust#116712
  * rust-lang/rust#116267
* rust-lang/rust#117377
* rust-lang/rust#117419



Co-authored-by: Alexis (Poliorcetics) Bourget <ab_github@poliorcetiq.eu>
Co-authored-by: Esteban Küber <esteban@kuber.com.ar>
Co-authored-by: David Tolnay <dtolnay@gmail.com>
Co-authored-by: Celina G. Val <celinval@amazon.com>
Co-authored-by: Michael Goulet <michael@errs.io>
Co-authored-by: bors <bors@rust-lang.org>
Co-authored-by: Camille GILLOT <gillot.camille@gmail.com>
Co-authored-by: lcnr <rust@lcnr.de>
Co-authored-by: Zalathar <Zalathar@users.noreply.github.com>
Co-authored-by: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-unix Operating system: Unix-like S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants