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);
+5 -3
View File
@@ -743,14 +743,16 @@ fn multithread_suite_spawned_callbacks() {
assert_eq!((s.multi_thread)(counter_worker, 8, raw as *mut c_void), OK);
}
for i in 0..8 {
let name = Box::leak(format!("ctr{i}").into_boxed_str());
// C 侧按 NUL 结尾读名字——必须经 cs() 包成 CString(裸
// `str::as_ptr()` 不带 NUL,CStr::from_ptr 会读越界)。
let name = cs(&format!("ctr{i}"));
let mut v = 0;
// 注意 `&*set`(Arc 负载)而非 `&set`(Arc 结构体)。
// 注意传 `&*set`(Arc 负载)而非 `&set`(Arc 结构体)。
unsafe {
assert_eq!(
(ps.get_int)(
&*set as *const _ as *mut c_void,
name.as_ptr() as *const c_char,
name.as_ptr(),
0,
&mut v
),
+3 -3
View File
@@ -139,12 +139,12 @@ if [ -d /opt/homebrew/lib/pkgconfig/openjpeg ]; then
fi
enable_if_pkg libopenjp2 libopenjpeg
# openh264 is redundant for us (decode: FFmpeg's native h264; encode:
# x264) and its MinGW package does not satisfy the static link — skip it
# on Windows.
# x264) and snappy only feeds the hap encoder; neither MinGW package
# satisfies the static link — skip both on Windows.
if [ -z "${MSYSTEM:-}" ]; then
enable_if_pkg openh264 libopenh264
enable_if_pkg snappy libsnappy
fi
enable_if_pkg snappy libsnappy
enable_if_pkg wavpack libwavpack
enable_if_pkg webp libwebp
enable_if_pkg xvid libxvid