Skip to content

Commit

Permalink
Let user invoke UB if they choose
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Dec 22, 2022
1 parent 8dfc955 commit b5c4bc1
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 28 deletions.
4 changes: 1 addition & 3 deletions tests/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,7 @@ fn weeks_in_year() {
fn local_offset_soundness() {
use time::util::local_offset::*;

// Safety for these calls: Technically they are unsound, as cargo runs tests in parallel.
// However, the odds of a test failing as a result of this is extremely low. It is better to
// test that these methods function as expected than to worry about a rare segfault.
// Safety: cargo does not mutate the environment while tests are running.

assert_eq!(get_soundness(), Soundness::Sound);
unsafe { set_soundness(Soundness::Unsound) };
Expand Down
34 changes: 9 additions & 25 deletions time/src/sys/local_offset_at/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,31 +121,15 @@ pub(super) fn local_offset_at(datetime: OffsetDateTime) -> Option<UtcOffset> {
// If the `num_threads` crate is incapable of determining the number of running threads, then
// we conservatively return `None` to avoid a soundness bug.

// In release mode, let the user invoke undefined behavior if they so choose.
#[cfg(not(debug_assertions))]
if local_offset::get_soundness() == Soundness::Sound
&& num_threads::is_single_threaded() != Some(true)
if local_offset::get_soundness() == Soundness::Unsound
|| num_threads::is_single_threaded() == Some(true)
{
return None;
}
// In debug mode, abort the program if the user would have invoked undefined behavior.
#[cfg(debug_assertions)]
if num_threads::is_single_threaded() != Some(true) {
if local_offset::get_soundness() == Soundness::Unsound {
eprintln!(
"WARNING: You are attempting to obtain the local UTC offset in a multi-threaded \
context. On Unix-like systems, this is undefined behavior. Either you or a \
dependency explicitly opted into unsound behavior. See the safety documentation \
for `time::local_offset::set_soundness` for further details."
);
std::process::abort();
}
return None;
let unix_timestamp = datetime.unix_timestamp();
// Safety: We have just confirmed that the process is single-threaded or the user has
// explicitly opted out of soundness.
let tm = unsafe { timestamp_to_tm(unix_timestamp) }?;
tm_to_offset(unix_timestamp, tm)
} else {
None
}

let unix_timestamp = datetime.unix_timestamp();
// Safety: We have just confirmed that the process is single-threaded or the user has explicitly
// opted out of soundness.
let tm = unsafe { timestamp_to_tm(unix_timestamp) }?;
tm_to_offset(unix_timestamp, tm)
}

0 comments on commit b5c4bc1

Please sign in to comment.