ci+fix: UCRT time functions on Windows; skip libsnappy on MinGW; NUL-terminated names in the mt test

- timeformat node: localtime_s/gmtime_s (reversed args, 64-bit time_t)
  on Windows — MinGW has no localtime_r/gmtime_r
- the multithread suite test passed non-NUL-terminated property names
  (str::as_ptr) to the C property suite — UB that resolved to garbage
  lookups on the CI runner
- libsnappy off on the MinGW FFmpeg build (only feeds the hap encoder;
  its pkg-config entry does not reach the static link)
This commit is contained in:
2026-08-21 09:17:29 +08:00
parent 032a3a559b
commit 7fb9c92931
3 changed files with 26 additions and 7 deletions
+18 -1
View File
@@ -67,11 +67,18 @@ struct Tm {
// `localtime_r` / `gmtime_r` (C `time.h`). Declared locally instead of
// pulling in a libc crate; both symbols live in the platform C library
// that `std` already links.
// that `std` already links. Windows (UCRT) has the `_s` variants with
// reversed argument order and a 64-bit time_t.
#[cfg(not(target_os = "windows"))]
extern "C" {
fn localtime_r(timep: *const c_long, result: *mut Tm) -> *mut Tm;
fn gmtime_r(timep: *const c_long, result: *mut Tm) -> *mut Tm;
}
#[cfg(target_os = "windows")]
extern "C" {
fn localtime_s(result: *mut Tm, timep: *const i64) -> i32;
fn gmtime_s(result: *mut Tm, timep: *const i64) -> i32;
}
/// Expand Qt date/time format tokens (`QDateTime::toString` syntax):
/// the field tokens d/dd, M/MM, yy/yyyy, h/hh, H/HH, m/mm, s/ss, z/zz/zzz,
@@ -287,6 +294,7 @@ impl NodeBehavior for TimeFormatNode {
let ms = (ms_since_epoch % 1000) as i32;
let mut tm: Tm = unsafe { std::mem::zeroed() };
#[cfg(not(target_os = "windows"))]
unsafe {
if to_bool(&local_val) {
localtime_r(&secs, &mut tm);
@@ -294,6 +302,15 @@ impl NodeBehavior for TimeFormatNode {
gmtime_r(&secs, &mut tm);
}
}
#[cfg(target_os = "windows")]
unsafe {
let secs64 = secs as i64;
if to_bool(&local_val) {
localtime_s(&mut tm, &secs64);
} else {
gmtime_s(&mut tm, &secs64);
}
}
let output = format_date_time(&tm, ms, &to_text(&format_val));
table.push(crate::value::ValueType::Text, NodeValue::Text(output), None);