Skip to content

Commit a7e7640

Browse files
committed
fix compilation with new new nightly VaList
In 2025-12-05, a Rust pull request at rust-lang/rust#141980 reworked the `VaList` implementation to be abi-compatible with C. This broke: * the `printf-compat` implementation, which is fixed in version 0.3 * pretty much every function that methods of `VaList` (most commonly `as_va_list`), since they no longer exist Here, we fix both of those problems and update the compiler version in `rust-toolchain.toml` to be the oldest compiler that will already have this new implementation. Updating the compiler has created 2 unforseen problems: 1. When unwinding, the new Rust version now prints the process's PID. This means for the `c-gull-unwinding` we can no longer use the `assert_cmd` API, as it does not expose the child PID to us. 2. The `c-gull/src/nss.rs` had 3 extra warnings of operations whose results were unused. This was also breaking some other tests. Both of these were also fixed.
1 parent a2f804a commit a7e7640

File tree

7 files changed

+92
-79
lines changed

7 files changed

+92
-79
lines changed

c-gull/src/nss.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,8 @@ unsafe fn getgr_r(
305305
};
306306
let pad = align_of::<*const c_char>() - (buf.addr()) % align_of::<*const c_char>();
307307
buf = buf.add(pad);
308-
buflen -= pad;
309308
let gr_mem = buf.cast::<*mut c_char>();
310309
buf = gr_mem.add(num_members + 1).cast::<c_char>();
311-
buflen -= buf.addr() - gr_mem.addr();
312310

313311
let mut cur_mem = gr_mem;
314312
if num_members != 0 {
@@ -319,7 +317,6 @@ unsafe fn getgr_r(
319317
buf = buf.add(member.len());
320318
write(buf, 0);
321319
buf = buf.add(1);
322-
buflen -= member.len() + 1;
323320
}
324321
}
325322
write(cur_mem, null_mut());

c-scape/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ rand = { version = "0.9.0", default-features = false }
3434
rustix-dlmalloc = { version = "0.2.1", optional = true }
3535
rustix-openpty = "0.2.0"
3636
bitflags = { version = "2.4.1", default-features = false }
37-
printf-compat = { version = "0.2.1", default-features = false }
37+
printf-compat = { version = "0.3.0", default-features = false }
3838
num-complex = { version = "0.4.4", default-features = false, features = ["libm"] }
3939
posix-regex = { version = "0.1.1", features = ["no_std"] }
4040

c-scape/src/fs/fcntl.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,16 @@ use libc::c_int;
99
use crate::convert_res;
1010

1111
#[no_mangle]
12-
unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
13-
let args = args.as_va_list();
12+
unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, args: ...) -> c_int {
1413
_fcntl::<libc::flock>(fd, cmd, args)
1514
}
1615

1716
#[no_mangle]
18-
unsafe extern "C" fn fcntl64(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
19-
let args = args.as_va_list();
17+
unsafe extern "C" fn fcntl64(fd: c_int, cmd: c_int, args: ...) -> c_int {
2018
_fcntl::<libc::flock64>(fd, cmd, args)
2119
}
2220

23-
unsafe fn _fcntl<FlockTy: Flock>(fd: c_int, cmd: c_int, mut args: VaList<'_, '_>) -> c_int {
21+
unsafe fn _fcntl<FlockTy: Flock>(fd: c_int, cmd: c_int, mut args: VaList<'_>) -> c_int {
2422
match cmd {
2523
libc::F_GETFL => {
2624
libc!(libc::fcntl(fd, libc::F_GETFL));

c-scape/src/stdio.rs

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -714,30 +714,24 @@ unsafe fn parse_oflags(mode: *const c_char) -> Option<OFlags> {
714714
}
715715

716716
#[no_mangle]
717-
unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
718-
let va_list = args.as_va_list();
719-
vprintf(fmt, va_list)
717+
unsafe extern "C" fn printf(fmt: *const c_char, args: ...) -> c_int {
718+
vprintf(fmt, args)
720719
}
721720

722721
#[no_mangle]
723-
unsafe extern "C" fn vprintf(fmt: *const c_char, va_list: VaList<'_, '_>) -> c_int {
722+
unsafe extern "C" fn vprintf(fmt: *const c_char, va_list: VaList<'_>) -> c_int {
724723
//libc!(libc::vprintf(fmt, va_list));
725724

726725
vfprintf(stdout, fmt, va_list)
727726
}
728727

729728
#[no_mangle]
730-
unsafe extern "C" fn sprintf(ptr: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
731-
let va_list = args.as_va_list();
732-
vsprintf(ptr, fmt, va_list)
729+
unsafe extern "C" fn sprintf(ptr: *mut c_char, fmt: *const c_char, args: ...) -> c_int {
730+
vsprintf(ptr, fmt, args)
733731
}
734732

735733
#[no_mangle]
736-
unsafe extern "C" fn vsprintf(
737-
ptr: *mut c_char,
738-
fmt: *const c_char,
739-
va_list: VaList<'_, '_>,
740-
) -> c_int {
734+
unsafe extern "C" fn vsprintf(ptr: *mut c_char, fmt: *const c_char, va_list: VaList<'_>) -> c_int {
741735
//libc!(libc::vsprintf(ptr, fmt, va_list));
742736

743737
let mut out = String::new();
@@ -762,18 +756,17 @@ unsafe extern "C" fn snprintf(
762756
ptr: *mut c_char,
763757
len: usize,
764758
fmt: *const c_char,
765-
mut args: ...
759+
args: ...
766760
) -> c_int {
767-
let va_list = args.as_va_list();
768-
vsnprintf(ptr, len, fmt, va_list)
761+
vsnprintf(ptr, len, fmt, args)
769762
}
770763

771764
#[no_mangle]
772765
unsafe extern "C" fn vsnprintf(
773766
ptr: *mut c_char,
774767
len: usize,
775768
fmt: *const c_char,
776-
va_list: VaList<'_, '_>,
769+
va_list: VaList<'_>,
777770
) -> c_int {
778771
//libc!(libc::vsnprintf(ptr, len, fmt, va_list));
779772

@@ -797,13 +790,12 @@ unsafe extern "C" fn vsnprintf(
797790
}
798791

799792
#[no_mangle]
800-
unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
801-
let va_list = args.as_va_list();
802-
vdprintf(fd, fmt, va_list)
793+
unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, args: ...) -> c_int {
794+
vdprintf(fd, fmt, args)
803795
}
804796

805797
#[no_mangle]
806-
unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, va_list: VaList<'_, '_>) -> c_int {
798+
unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, va_list: VaList<'_>) -> c_int {
807799
//libc!(libc::vdprintf(fd, fmt, va_list));
808800

809801
let mut out = String::new();
@@ -830,16 +822,15 @@ unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, va_list: VaList<'_,
830822
}
831823

832824
#[no_mangle]
833-
unsafe extern "C" fn fprintf(file: *mut libc::FILE, fmt: *const c_char, mut args: ...) -> c_int {
834-
let va_list = args.as_va_list();
835-
vfprintf(file, fmt, va_list)
825+
unsafe extern "C" fn fprintf(file: *mut libc::FILE, fmt: *const c_char, args: ...) -> c_int {
826+
vfprintf(file, fmt, args)
836827
}
837828

838829
#[no_mangle]
839830
unsafe extern "C" fn vfprintf(
840831
file: *mut libc::FILE,
841832
fmt: *const c_char,
842-
va_list: VaList<'_, '_>,
833+
va_list: VaList<'_>,
843834
) -> c_int {
844835
//libc!(libc::vfprintf(file, fmt, va_list));
845836

@@ -858,9 +849,9 @@ unsafe extern "C" fn vfprintf(
858849
unsafe extern "C" fn vasprintf(
859850
strp: *mut *mut c_char,
860851
fmt: *const c_char,
861-
va_list: VaList<'_, '_>,
852+
va_list: VaList<'_>,
862853
) -> c_int {
863-
let len = va_list.with_copy(|va_list| vsnprintf(null_mut(), 0, fmt, va_list));
854+
let len = vsnprintf(null_mut(), 0, fmt, va_list.clone());
864855
if len < 0 {
865856
return -1;
866857
}
@@ -875,9 +866,8 @@ unsafe extern "C" fn vasprintf(
875866
}
876867

877868
#[no_mangle]
878-
unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
879-
let va_list = args.as_va_list();
880-
vasprintf(strp, fmt, va_list)
869+
unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
870+
vasprintf(strp, fmt, args)
881871
}
882872

883873
#[no_mangle]

c-scape/src/stdio/chk.rs

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ unsafe extern "C" fn __snprintf_chk(
1717
flag: c_int,
1818
slen: size_t,
1919
fmt: *const c_char,
20-
mut args: ...
20+
args: ...
2121
) -> c_int {
22-
let va_list = args.as_va_list();
23-
__vsnprintf_chk(ptr, len, flag, slen, fmt, va_list)
22+
__vsnprintf_chk(ptr, len, flag, slen, fmt, args)
2423
}
2524

2625
// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---vsnprintf-chk-1.html>
@@ -31,7 +30,7 @@ unsafe extern "C" fn __vsnprintf_chk(
3130
flag: c_int,
3231
slen: size_t,
3332
fmt: *const c_char,
34-
va_list: VaList<'_, '_>,
33+
va_list: VaList<'_>,
3534
) -> c_int {
3635
if slen < len {
3736
__chk_fail();
@@ -51,10 +50,9 @@ unsafe extern "C" fn __sprintf_chk(
5150
flag: c_int,
5251
strlen: size_t,
5352
format: *const c_char,
54-
mut args: ...
53+
args: ...
5554
) -> c_int {
56-
let va_list = args.as_va_list();
57-
__vsprintf_chk(ptr, flag, strlen, format, va_list)
55+
__vsprintf_chk(ptr, flag, strlen, format, args)
5856
}
5957

6058
#[no_mangle]
@@ -63,7 +61,7 @@ unsafe extern "C" fn __vsprintf_chk(
6361
flag: c_int,
6462
strlen: size_t,
6563
fmt: *const c_char,
66-
va_list: VaList<'_, '_>,
64+
va_list: VaList<'_>,
6765
) -> c_int {
6866
if flag > 0 {
6967
unimplemented!("__USE_FORTIFY_LEVEL > 0");
@@ -88,10 +86,9 @@ unsafe extern "C" fn __fprintf_chk(
8886
file: *mut libc::FILE,
8987
flag: c_int,
9088
fmt: *const c_char,
91-
mut args: ...
89+
args: ...
9290
) -> c_int {
93-
let va_list = args.as_va_list();
94-
__vfprintf_chk(file, flag, fmt, va_list)
91+
__vfprintf_chk(file, flag, fmt, args)
9592
}
9693

9794
// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---vfprintf-chk-1.html>
@@ -100,7 +97,7 @@ unsafe extern "C" fn __vfprintf_chk(
10097
file: *mut libc::FILE,
10198
flag: c_int,
10299
fmt: *const c_char,
103-
va_list: VaList<'_, '_>,
100+
va_list: VaList<'_>,
104101
) -> c_int {
105102
if flag > 0 {
106103
unimplemented!("__USE_FORTIFY_LEVEL > 0");
@@ -113,17 +110,12 @@ unsafe extern "C" fn __vfprintf_chk(
113110

114111
// <https://refspecs.linuxbase.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/baselib---printf-chk-1.html>
115112
#[no_mangle]
116-
unsafe extern "C" fn __printf_chk(flag: c_int, fmt: *const c_char, mut args: ...) -> c_int {
117-
let va_list = args.as_va_list();
118-
__vprintf_chk(flag, fmt, va_list)
113+
unsafe extern "C" fn __printf_chk(flag: c_int, fmt: *const c_char, args: ...) -> c_int {
114+
__vprintf_chk(flag, fmt, args)
119115
}
120116

121117
#[no_mangle]
122-
unsafe extern "C" fn __vprintf_chk(
123-
flag: c_int,
124-
fmt: *const c_char,
125-
va_list: VaList<'_, '_>,
126-
) -> c_int {
118+
unsafe extern "C" fn __vprintf_chk(flag: c_int, fmt: *const c_char, va_list: VaList<'_>) -> c_int {
127119
if flag > 0 {
128120
unimplemented!("__USE_FORTIFY_LEVEL > 0");
129121
}
@@ -138,18 +130,17 @@ unsafe extern "C" fn __asprintf_chk(
138130
strp: *mut *mut c_char,
139131
flag: c_int,
140132
fmt: *const c_char,
141-
mut args: ...
133+
args: ...
142134
) -> c_int {
143-
let va_list = args.as_va_list();
144-
__vasprintf_chk(strp, flag, fmt, va_list)
135+
__vasprintf_chk(strp, flag, fmt, args)
145136
}
146137

147138
#[no_mangle]
148139
unsafe extern "C" fn __vasprintf_chk(
149140
strp: *mut *mut c_char,
150141
flag: c_int,
151142
fmt: *const c_char,
152-
va_list: VaList<'_, '_>,
143+
va_list: VaList<'_>,
153144
) -> c_int {
154145
if flag > 0 {
155146
unimplemented!("__USE_FORTIFY_LEVEL > 0");
@@ -159,22 +150,16 @@ unsafe extern "C" fn __vasprintf_chk(
159150
}
160151

161152
#[no_mangle]
162-
unsafe extern "C" fn __dprintf_chk(
163-
fd: c_int,
164-
flag: c_int,
165-
fmt: *const c_char,
166-
mut args: ...
167-
) -> c_int {
168-
let va_list = args.as_va_list();
169-
__vdprintf_chk(fd, flag, fmt, va_list)
153+
unsafe extern "C" fn __dprintf_chk(fd: c_int, flag: c_int, fmt: *const c_char, args: ...) -> c_int {
154+
__vdprintf_chk(fd, flag, fmt, args)
170155
}
171156

172157
#[no_mangle]
173158
unsafe extern "C" fn __vdprintf_chk(
174159
fd: c_int,
175160
flag: c_int,
176161
fmt: *const c_char,
177-
va_list: VaList<'_, '_>,
162+
va_list: VaList<'_>,
178163
) -> c_int {
179164
if flag > 0 {
180165
unimplemented!("__USE_FORTIFY_LEVEL > 0");

rust-toolchain.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[toolchain]
2-
channel = "nightly-2025-04-28"
2+
channel = "nightly-2025-12-07"
33
components = ["rustc", "cargo", "rust-std", "rust-src", "rustfmt"]

tests/example_crates.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,57 @@ fn example_crate_c_scape_unwinding() {
140140

141141
#[test]
142142
fn example_crate_c_gull_unwinding() {
143-
test_crate(
144-
"c-gull-unwinding",
145-
&[],
146-
&[("RUST_BACKTRACE", "0")],
147-
"Hello, world!\nHello world using libc `printf`!\n",
148-
"\nthread 'main' panicked at src/main.rs:18:5:\ncatch me!\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n",
149-
None,
143+
// Note: Rust's default unwind now prints a message with the process's PID. The assert_cmd
144+
// command does not let us get the child's PID. So we have to use the std::process::Command API
145+
// instead.
146+
use std::process::Command;
147+
use std::process::Stdio;
148+
149+
#[cfg(target_arch = "x86_64")]
150+
let arch = "x86_64";
151+
#[cfg(target_arch = "aarch64")]
152+
let arch = "aarch64";
153+
#[cfg(target_arch = "riscv64")]
154+
let arch = "riscv64gc";
155+
#[cfg(target_arch = "x86")]
156+
let arch = "i686";
157+
#[cfg(target_arch = "arm")]
158+
let arch = "armv5te";
159+
#[cfg(target_env = "gnueabi")]
160+
let env = "gnueabi";
161+
#[cfg(all(target_env = "gnu", target_abi = "eabi"))]
162+
let env = "gnueabi";
163+
#[cfg(all(target_env = "gnu", not(target_abi = "eabi")))]
164+
let env = "gnu";
165+
166+
let mut command = Command::new("cargo");
167+
command.arg("run").arg("--quiet");
168+
command.arg(&format!("--target={}-unknown-linux-{}", arch, env));
169+
170+
command.env("RUST_BACKTRACE", "0");
171+
command.current_dir("example-crates/c-gull-unwinding");
172+
173+
command.stdout(Stdio::piped());
174+
command.stderr(Stdio::piped());
175+
176+
let child = command.spawn().unwrap();
177+
let pid = child.id();
178+
let output = child.wait_with_output().unwrap();
179+
180+
assert_eq!(
181+
std::str::from_utf8(&output.stdout).unwrap(),
182+
"Hello, world!\nHello world using libc `printf`!\n"
183+
);
184+
assert_eq!(
185+
std::str::from_utf8(&output.stderr).unwrap(),
186+
format!(
187+
"\nthread 'main' ({pid}) panicked at src/main.rs:18:5:\n\
188+
catch me!\n\
189+
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n"
190+
)
191+
.as_str()
150192
);
193+
assert!(output.status.success());
151194
}
152195

153196
#[test]

0 commit comments

Comments
 (0)