1
1
//! Get the system's UTC offset on Unix.
2
- # [ cfg ( any ( target_os = "linux" , target_os = "freebsd" , unsound_local_offset ) ) ]
2
+
3
3
use core:: convert:: TryInto ;
4
- #[ cfg( any( target_os = "linux" , target_os = "freebsd" , unsound_local_offset) ) ]
5
4
use core:: mem:: MaybeUninit ;
6
5
7
6
use crate :: { OffsetDateTime , UtcOffset } ;
8
7
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
-
18
8
/// Convert the given Unix timestamp to a `libc::tm`. Returns `None` on any error.
19
9
///
20
10
/// # Safety
@@ -24,7 +14,6 @@ pub(super) fn local_offset_at(_datetime: OffsetDateTime) -> Option<UtcOffset> {
24
14
/// This method will remain `unsafe` until `std::env::set_var` is deprecated or has its behavior
25
15
/// altered. This method is, on its own, safe. It is the presence of a safe, unsound way to set
26
16
/// environment variables that makes it unsafe.
27
- #[ cfg( any( target_os = "linux" , target_os = "freebsd" , unsound_local_offset) ) ]
28
17
unsafe fn timestamp_to_tm ( timestamp : i64 ) -> Option < libc:: tm > {
29
18
extern "C" {
30
19
#[ cfg_attr( target_os = "netbsd" , link_name = "__tzset50" ) ]
@@ -56,8 +45,10 @@ unsafe fn timestamp_to_tm(timestamp: i64) -> Option<libc::tm> {
56
45
57
46
/// Convert a `libc::tm` to a `UtcOffset`. Returns `None` on any error.
58
47
// `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
+ ) ) ) ]
61
52
fn tm_to_offset ( tm : libc:: tm ) -> Option < UtcOffset > {
62
53
let seconds: i32 = tm. tm_gmtoff . try_into ( ) . ok ( ) ?;
63
54
UtcOffset :: from_hms (
@@ -69,8 +60,10 @@ fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
69
60
}
70
61
71
62
/// 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
+ ) ) ]
74
67
fn tm_to_offset ( tm : libc:: tm ) -> Option < UtcOffset > {
75
68
use core:: convert:: TryFrom ;
76
69
@@ -107,12 +100,13 @@ fn tm_to_offset(tm: libc::tm) -> Option<UtcOffset> {
107
100
}
108
101
109
102
/// Obtain the system's UTC offset.
110
- #[ cfg( any( target_os = "linux" , target_os = "freebsd" , unsound_local_offset) ) ]
111
103
pub ( super ) fn local_offset_at ( datetime : OffsetDateTime ) -> Option < UtcOffset > {
112
104
// Ensure that the process is single-threaded unless the user has explicitly opted out of this
113
105
// check. This is to prevent issues with the environment being mutated by a different thread in
114
106
// the process while execution of this function is taking place, which can cause a segmentation
115
107
// 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.
116
110
if !cfg ! ( unsound_local_offset) && num_threads:: is_single_threaded ( ) != Some ( true ) {
117
111
return None ;
118
112
}
0 commit comments