Skip to content

Commit 4e83e2d

Browse files
committed
fix: fix differing bitwidth routines in win x86 gnu
Until #5032, whenever `libc` was running under Windows x86 with GNU, the default bit-width of `time_t` values was 32-bits. This doesn't quite align with the defaults in MSVC and `mingw`, but that's been addressed in that PR. This PR is a quick patch for stable, as the changes in #5032 are not backwards-compatible. It separates the routines that under Windows use `time_t` values and changes their link-time symbols to the 32-bit variants exposed in both MSVC and `mingw`, for the affected target platform/environment. It also adds a test, akin to the one in #5032, that should ensure the correct bit-widths are in use for both the types and the linked routine symbols.
1 parent 088a284 commit 4e83e2d

File tree

2 files changed

+55
-8
lines changed

2 files changed

+55
-8
lines changed

libc-test/tests/windows_time.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Ensures Windows `time`-related routines align with `libc`'s interface. By
2+
//! default, both MSVC and GNU (under `mingw`) expose 64-bit symbols, but in
3+
//! stable we need to cope with a 32-bit `time-t`, so the routines should link
4+
//! to their 32-bit variants.
5+
6+
#![cfg(windows)]
7+
8+
/// Ensures a 64-bit write is performed on values that should always be 64 bits,
9+
/// and that a corresponding 32-bit write is performed on values that should be
10+
/// 32 bits. This basically makes sure `time_t`'s bit-width aligns with those of
11+
/// functions that expect it as a parameter.
12+
#[test]
13+
fn test_bitwidth_store() {
14+
#[cfg(all(target_arch = "x86", target_env = "gnu"))]
15+
assert_eq!(size_of::<libc::time_t>(), 4);
16+
#[cfg(not(all(target_arch = "x86", target_env = "gnu")))]
17+
assert_eq!(size_of::<libc::time_t>(), 8);
18+
19+
let mut time_values: [libc::time_t; 2] = [123, 456];
20+
let ptr = time_values.as_mut_ptr();
21+
22+
unsafe { libc::time(ptr) };
23+
24+
assert_ne!(time_values[0], 123);
25+
assert_eq!(time_values[1], 456);
26+
}

src/windows/mod.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,11 +389,36 @@ extern "C" {
389389
pub fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t;
390390
pub fn raise(signum: c_int) -> c_int;
391391

392+
// By default, the following link to 64-bit variants where the expected
393+
// `time_t` is also 64-bits.
394+
//
395+
// Under Windows x86 with GNU, `time_t` is still 32-bit wide on stable, so
396+
// these routines have to link with their 32-bit variants.
397+
//
398+
// FIXME(#5062): once that PR gets merged, add `not(windows_gnu_time64)` to
399+
// the below predicate, within the `all()` clause.
400+
cfg_if! {
401+
if #[cfg(all(target_arch = "x86", target_env = "gnu"))] {
402+
#[link_name = "_ctime32"]
403+
pub fn ctime(sourceTime: *const time_t) -> *mut c_char;
404+
#[link_name = "_difftime32"]
405+
pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double;
406+
#[link_name = "_gmtime32_s"]
407+
pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int;
408+
#[link_name = "_localtime32_s"]
409+
pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t;
410+
#[link_name = "_time32"]
411+
pub fn time(destTime: *mut time_t) -> time_t;
412+
} else {
413+
pub fn ctime(sourceTime: *const time_t) -> *mut c_char;
414+
pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double;
415+
pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int;
416+
pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t;
417+
pub fn time(destTime: *mut time_t) -> time_t;
418+
}
419+
}
420+
392421
pub fn clock() -> clock_t;
393-
pub fn ctime(sourceTime: *const time_t) -> *mut c_char;
394-
pub fn difftime(timeEnd: time_t, timeStart: time_t) -> c_double;
395-
#[link_name = "_gmtime64_s"]
396-
pub fn gmtime_s(destTime: *mut tm, srcTime: *const time_t) -> c_int;
397422
#[link_name = "_get_daylight"]
398423
pub fn get_daylight(hours: *mut c_int) -> errno_t;
399424
#[link_name = "_get_dstbias"]
@@ -407,10 +432,6 @@ extern "C" {
407432
size_in_bytes: size_t,
408433
index: c_int,
409434
) -> errno_t;
410-
#[link_name = "_localtime64_s"]
411-
pub fn localtime_s(tmDest: *mut tm, sourceTime: *const time_t) -> crate::errno_t;
412-
#[link_name = "_time64"]
413-
pub fn time(destTime: *mut time_t) -> time_t;
414435
#[link_name = "_tzset"]
415436
pub fn tzset();
416437
#[link_name = "_chmod"]

0 commit comments

Comments
 (0)