Skip to content

Commit bf5f830

Browse files
committed
Defer to num_threads for OS support
1 parent f6baa3f commit bf5f830

File tree

3 files changed

+16
-42
lines changed

3 files changed

+16
-42
lines changed

.github/workflows/build.yaml

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,9 @@ jobs:
156156
matrix:
157157
rust: ["1.53", stable]
158158
os:
159-
- { name: Ubuntu, value: ubuntu-20.04, has_local_offset: true }
160-
- { name: Windows, value: windows-latest, has_local_offset: true }
161-
- { name: MacOS, value: macOS-latest, has_local_offset: false }
159+
- { name: Ubuntu, value: ubuntu-20.04 }
160+
- { name: Windows, value: windows-latest }
161+
- { name: MacOS, value: macOS-latest }
162162

163163
steps:
164164
- name: Checkout sources
@@ -203,24 +203,6 @@ jobs:
203203
--features macros
204204
if: matrix.os.has_local_offset == true
205205

206-
# Due to the soundness bug on Unix-like platforms, adding the local-offset flag doesn't
207-
# actually add any new behavior. Since we know nothing changes, we can unconditionally enable
208-
# the flag.
209-
- name: Check feature powerset
210-
uses: actions-rs/cargo@v1
211-
with:
212-
command: hack
213-
args: |
214-
check
215-
--feature-powerset
216-
--optional-deps
217-
--group-features serde,rand
218-
--group-features formatting,parsing
219-
--group-features serde-human-readable,serde-well-known
220-
--exclude-features default,quickcheck-dep,time-macros,itoa
221-
--features macros,local-offset
222-
if: matrix.os.has_local_offset == false
223-
224206
- name: Test
225207
uses: actions-rs/cargo@v1
226208
with:

Cargo.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,9 @@ rand = { version = "0.8.4", optional = true, default-features = false }
4444
serde = { version = "1.0.126", optional = true, default-features = false }
4545
time-macros = { version = "=0.2.3", path = "time-macros", optional = true }
4646

47-
[target.'cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))'.dependencies]
47+
[target.'cfg(target_family = "unix")'.dependencies]
4848
libc = "0.2.98"
49-
50-
[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
51-
num_threads = "0.1.0"
49+
num_threads = "0.1.2"
5250

5351
[dev-dependencies]
5452
rand = { version = "0.8.4", default-features = false }

src/sys/local_offset_at/unix.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,10 @@
11
//! Get the system's UTC offset on Unix.
2-
#[cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))]
2+
33
use core::convert::TryInto;
4-
#[cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))]
54
use core::mem::MaybeUninit;
65

76
use crate::{OffsetDateTime, UtcOffset};
87

9-
/// Obtain the system's UTC offset.
10-
// This fallback is used whenever an operating system doesn't have a method below for determine if a
11-
// process is single threaded.
12-
#[cfg(not(any(target_os = "linux", target_os = "freebsd", unsound_local_offset)))]
13-
#[allow(clippy::missing_const_for_fn)]
14-
pub(super) fn local_offset_at(_datetime: OffsetDateTime) -> Option<UtcOffset> {
15-
None
16-
}
17-
188
/// Convert the given Unix timestamp to a `libc::tm`. Returns `None` on any error.
199
///
2010
/// # Safety
@@ -24,7 +14,6 @@ pub(super) fn local_offset_at(_datetime: OffsetDateTime) -> Option<UtcOffset> {
2414
/// This method will remain `unsafe` until `std::env::set_var` is deprecated or has its behavior
2515
/// altered. This method is, on its own, safe. It is the presence of a safe, unsound way to set
2616
/// environment variables that makes it unsafe.
27-
#[cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))]
2817
unsafe fn timestamp_to_tm(timestamp: i64) -> Option<libc::tm> {
2918
extern "C" {
3019
#[cfg_attr(target_os = "netbsd", link_name = "__tzset50")]
@@ -56,8 +45,10 @@ unsafe fn timestamp_to_tm(timestamp: i64) -> Option<libc::tm> {
5645

5746
/// Convert a `libc::tm` to a `UtcOffset`. Returns `None` on any error.
5847
// `tm_gmtoff` extension
59-
#[cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))]
60-
#[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
48+
#[cfg(not(all(
49+
unsound_local_offset,
50+
any(target_os = "solaris", target_os = "illumos")
51+
)))]
6152
fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
6253
let seconds: i32 = tm.tm_gmtoff.try_into().ok()?;
6354
UtcOffset::from_hms(
@@ -69,8 +60,10 @@ fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
6960
}
7061

7162
/// Convert a `libc::tm` to a `UtcOffset`. Returns `None` on any error.
72-
#[cfg(unsound_local_offset)]
73-
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
63+
#[cfg(all(
64+
unsound_local_offset,
65+
any(target_os = "solaris", target_os = "illumos")
66+
))]
7467
fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
7568
use core::convert::TryFrom;
7669

@@ -107,12 +100,13 @@ fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
107100
}
108101

109102
/// Obtain the system's UTC offset.
110-
#[cfg(any(target_os = "linux", target_os = "freebsd", unsound_local_offset))]
111103
pub(super) fn local_offset_at(datetime: OffsetDateTime) -> Option<UtcOffset> {
112104
// Ensure that the process is single-threaded unless the user has explicitly opted out of this
113105
// check. This is to prevent issues with the environment being mutated by a different thread in
114106
// the process while execution of this function is taking place, which can cause a segmentation
115107
// fault by dereferencing a dangling pointer.
108+
// If the `num_threads` crate is incapable of determining the number of running threads, then
109+
// we conservatively return `None` to avoid a soundness bug.
116110
if !cfg!(unsound_local_offset) && num_threads::is_single_threaded() != Some(true) {
117111
return None;
118112
}

0 commit comments

Comments
 (0)