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

History update #1266

Merged
merged 1 commit into from Sep 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
98 changes: 48 additions & 50 deletions src/lib.rs
Expand Up @@ -378,27 +378,28 @@
//!
//! ## Relation between chrono and time 0.1
//!
//! Since Rust 0.7 the standard library had a `time` module. It moved to `libextra`, and then to a
//! `libtime` library shipped alongside the standard library. In 2014 the work on chrono started in
//! order to provide a full-featured date and time library in Rust. Some improvements from chrono
//! made it into the standard library, notably the `chrono::Duration` type was moved to
//! `std::time::Duration` ([rust#15934]).
//! Rust first had a `time` module added to `std` in its 0.7 release. It later moved to
//! `libextra`, and then to a `libtime` library shipped alongside the standard library. In 2014
//! work on chrono started in order to provide a full-featured date and time library in Rust.
//! Some improvements from chrono made it into the standard library; notably, `chrono::Duration`
//! was included as `std::time::Duration` ([rust#15934]) in 2014.
//!
//! In preparation of Rust 1.0 at the end of 2014 `libtime` was moved out of the Rust distro and
//! into the `time` crate to eventually be redesigned ([rust#18832], [rust#18858]), just like the
//! `num` and `rand` crates. Naturally chrono gained `time` as a dependency. `time` also started
//! re-exporting `std::time::Duration`. Later the standard library was changed to have a more
//! limited unsigned `Duration` type ([rust#24920], [RFC 1040]), while the `time` crate kept the
//! full functionality with `time::Duration`. And `time::Duration` was part of the public API of
//! chrono.
//! into the `time` crate to eventually be redesigned ([rust#18832], [rust#18858]), like the
//! `num` and `rand` crates. Of course chrono kept its dependency on this `time` crate. `time`
//! started re-exporting `std::time::Duration` during this period. Later, the standard library was
//! changed to have a more limited unsigned `Duration` type ([rust#24920], [RFC 1040]), while the
//! `time` crate kept the full functionality with `time::Duration`. `time::Duration` had been a
//! part of chrono's public API.
//!
//! By 2016 `time` 0.1 lived under the `rust-lang-deprecated` organisation and was not actively
//! maintained ([time#136]). Chrono absorbed the platform functionality and `Duration` type of the
//! time crate in [chrono#478] (the work started in [chrono#286]). But because of the
//! `time::Duration` type and to not make this a breaking change `time` would still remain as a
//! dependency. Crates could opt to use chrono without the `old-time` feature to drop the
//! dependency. During this time @jhpratt would take over `time` and release what amounts to a new
//! crate under time 0.2.
//! maintained ([time#136]). chrono absorbed the platform functionality and `Duration` type of the
//! `time` crate in [chrono#478] (the work started in [chrono#286]). In order to preserve
//! compatibility with downstream crates depending on `time` and `chrono` sharing a `Duration`
//! type, chrono kept depending on time 0.1. chrono offered the option to opt out of the `time`
pitdicker marked this conversation as resolved.
Show resolved Hide resolved
//! dependency by disabling the `oldtime` feature (swapping it out for an effectively similar
//! chrono type). In 2019, @jhpratt took over maintenance on the `time` crate and released what
//! amounts to a new crate as `time` 0.2.
//!
//! [rust#15934]: https://github.com/rust-lang/rust/pull/15934
//! [rust#18832]: https://github.com/rust-lang/rust/pull/18832#issuecomment-62448221
Expand All @@ -409,35 +410,29 @@
//! [chrono#286]: https://github.com/chronotope/chrono/pull/286
//! [chrono#478]: https://github.com/chronotope/chrono/pull/478
//!
//! #### Security advisories
//! ## Security advisories
//!
//! In november 2020 [CVE-2020-26235] and [RUSTSEC-2020-0071] were opened against the time crate,
//! and the start of quite some frustration for the rust ecosystem. @quininer found that calls to
//! `localtime_r` may be unsound ([chrono#499]). Eventually, almost a year later, this was also made
//! into a security advisory against chrono as [RUSTSEC-2020-0159], which had platform code similar
//! to `time`.
//! In November of 2020 [CVE-2020-26235] and [RUSTSEC-2020-0071] were opened against the `time` crate.
//! @quininer had found that calls to `localtime_r` may be unsound ([chrono#499]). Eventually, almost
//! a year later, this was also made into a security advisory against chrono as [RUSTSEC-2020-0159],
//! which had platform code similar to `time`.
//!
//! The issue: on Unix-like systems a process is given a time zone id or description via the `TZ`
//! environment variable. We need this time zone data to calculate the current local time from a
//! value that is in UTC, such as the time from the system clock. `time` 0.1 and chrono used the
//! POSIX function `localtime_r` to do the conversion to local time, which reads the `TZ` variable.
//! On Unix-like systems a process is given a timezone id or description via the `TZ` environment
//! variable. We need this timezone data to calculate the current local time from a value that is
//! in UTC, such as the time from the system clock. `time` 0.1 and chrono used the POSIX function
//! `localtime_r` to do the conversion to local time, which reads the `TZ` variable.
//!
//! Rust assumes the environment to be writable and uses locks to access it from multiple threads.
//! So do some other programming languages and libraries, but there is no shared locking mechanism.
//! More importantly POSIX declares modifying the environment in a multi-threaded process as unsafe,
//! and `getenv` in libc can't be changed to just take a lock because it returns a pointer to the
//! data (see [rust#27970] for more discussion).
//! Some other programming languages and libraries use similar locking strategies, but these are
//! typically not shared across languages. More importantly, POSIX declares modifying the
//! environment in a multi-threaded process as unsafe, and `getenv` in libc can't be changed to
//! take a lock because it returns a pointer to the data (see [rust#27970] for more discussion).
//!
//! Since version 4.20 chrono no longer uses `localtime_r` but uses rust code to query the time zone
//! (from the `TZ` variable or via `iana-time-zone` as a fallback) and work with data from the
//! system time zone database directly. This involves the logic for POSIX TZ Strings, and parsing
//! TZif files and working with their transition tables. The code mostly comes from the work by
//! @x-hgg-x on the [tz-rs crate].
//!
//! So when reading the `TZ` environment variable chrono now respects the Rust locks. However in
//! general it is probably best to avoid modifying the environment.
//!
//! The good thing to come from this is that we can improve beyond what the platform offers.
//! Since version 4.20 chrono no longer uses `localtime_r`, instead using Rust code to query the
//! timezone (from the `TZ` variable or via `iana-time-zone` as a fallback) and work with data
//! from the system timezone database directly. The code for this was forked from the [tz-rs crate]
//! by @x-hgg-x. As such, chrono now respects the Rust lock when reading the `TZ` environment
//! variable. In general, code should avoid modifying the environment.
//!
//! [CVE-2020-26235]: https://nvd.nist.gov/vuln/detail/CVE-2020-26235
//! [RUSTSEC-2020-0071]: https://rustsec.org/advisories/RUSTSEC-2020-0071
Expand All @@ -447,17 +442,20 @@
//! [chrono#677]: https://github.com/chronotope/chrono/pull/677
//! [tz-rs crate]: https://crates.io/crates/tz-rs
//!
//! #### Removing time 0.1
//! ## Removing time 0.1
//!
//! Still users of chrono would get a security advisory because of the time 0.1 dependency, which
//! was never fixed. We were careful not to break backwards compatibility with the `time::Duration`
//! type. But how many crates actually depend on this compatibility with time 0.1? Remember it was
//! unmaintained for multiple years, and now had much improved new releases. After a primitive
//! crater-like run it turned out only a tiny number of crates would break ([chrono#1095]), which we
//! reached out to if still maintained.
//! Because time 0.1 has been unmaintained for years, however, the security advisory mentioned
//! above has not been addressed. While chrono maintainers were careful not to break backwards
//! compatibility with the `time::Duration` type, there has been a long stream of issues from
//! users inquiring about the time 0.1 dependency with the vulnerability. We investigated the
//! potential breakage of removing the time 0.1 dependency in [chrono#1095] using a crater-like
//! experiment and determined that the potential for breaking (public) dependencies is very low.
//! We reached out to those few crates that did still depend on compatibility with time 0.1.
//!
//! With 0.4.30 chrono finally drops the time 0.1 dependency, making an end to the *many* security
//! advisory warnings against crates depending on chrono.
//! As such, for chrono 0.4.30 we have decided to swap out the time 0.1 `Duration` implementation
//! for a local one that will offer a strict superset of the existing API going forward. This
//! will prevent most downstream users from being affected by the security vulnerability in time
//! 0.1 while minimizing the ecosystem impact of semver-incompatible version churn.
//!
//! [chrono#1095]: https://github.com/chronotope/chrono/pull/1095

Expand Down