From 42c182fffe712b8166ac7492c50b9bdbd93dab9b Mon Sep 17 00:00:00 2001 From: Etienne Cordonnier Date: Sun, 18 Oct 2026 17:17:51 +0200 Subject: [PATCH 1/4] stdbuf: return stderr from the cygwin stderr getter __stdbuf_get_stderr read _stdin from the reent struct on cygwin, so stdbuf -e changed the buffering of stdin instead of stderr. Introduced in 54ba74bb7e ("Add more Cygwin support", #9686). --- src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index f1aa4dcb621..008f1340ce6 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -188,7 +188,7 @@ pub unsafe extern "C" fn __stdbuf_get_stderr() -> *mut FILE { fn __getreent() -> *mut _reent; } - unsafe { (*__getreent())._stdin } + unsafe { (*__getreent())._stderr } } #[cfg(not(any( From f08bb7a2d29901a4be68451c476eba2a277d8621 Mon Sep 17 00:00:00 2001 From: Etienne Cordonnier Date: Sun, 18 Oct 2026 17:53:53 +0200 Subject: [PATCH 2/4] stdbuf: test that the stream getters return their own streams Check that the stdin, stdout and stderr getters give file descriptors 0, 1 and 2. This would have caught the cygwin stderr getter returning stdin. Enable the unit tests of libstdbuf for this. --- src/uu/stdbuf/src/libstdbuf/Cargo.toml | 1 - src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/uu/stdbuf/src/libstdbuf/Cargo.toml b/src/uu/stdbuf/src/libstdbuf/Cargo.toml index df9e5a81a03..9e8a5a64bb3 100644 --- a/src/uu/stdbuf/src/libstdbuf/Cargo.toml +++ b/src/uu/stdbuf/src/libstdbuf/Cargo.toml @@ -14,7 +14,6 @@ rust-version.workspace = true name = "stdbuf" path = "src/libstdbuf.rs" crate-type = ["cdylib"] -test = false [dependencies] ctor = { workspace = true } diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index 008f1340ce6..0761cdbd493 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -249,3 +249,18 @@ pub unsafe extern "C" fn __stdbuf() { set_buffer(unsafe { __stdbuf_get_stdout() }, &val); } } + +#[cfg(all(test, unix))] +mod tests { + use super::*; + + // Each getter must return its own stream, not another one. + #[test] + fn test_stream_getters_return_matching_streams() { + unsafe { + assert_eq!(fileno(__stdbuf_get_stdin()), 0); + assert_eq!(fileno(__stdbuf_get_stdout()), 1); + assert_eq!(fileno(__stdbuf_get_stderr()), 2); + } + } +} From 62799f7d766e34d3d885791a3ca7cf65960710c9 Mon Sep 17 00:00:00 2001 From: Etienne Cordonnier Date: Mon, 19 Oct 2026 12:54:23 +0200 Subject: [PATCH 3/4] stdbuf: read Apple/FreeBSD stdio pointers as statics __stdinp, __stdoutp and __stderrp are data variables, not functions. Calling them jumped into data and crashed with SIGBUS on macOS. --- src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index 0761cdbd493..8584386c478 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -24,9 +24,9 @@ pub unsafe extern "C" fn __stdbuf_get_stdin() -> *mut FILE { #[cfg(any(target_vendor = "apple", target_os = "freebsd"))] { unsafe extern "C" { - fn __stdinp() -> *mut FILE; + static mut __stdinp: *mut FILE; } - unsafe { __stdinp() } + unsafe { __stdinp } } #[cfg(target_os = "openbsd")] @@ -87,9 +87,9 @@ pub unsafe extern "C" fn __stdbuf_get_stdout() -> *mut FILE { #[cfg(any(target_vendor = "apple", target_os = "freebsd"))] { unsafe extern "C" { - fn __stdoutp() -> *mut FILE; + static mut __stdoutp: *mut FILE; } - unsafe { __stdoutp() } + unsafe { __stdoutp } } #[cfg(target_os = "openbsd")] @@ -150,9 +150,9 @@ pub unsafe extern "C" fn __stdbuf_get_stderr() -> *mut FILE { #[cfg(any(target_vendor = "apple", target_os = "freebsd"))] { unsafe extern "C" { - fn __stderrp() -> *mut FILE; + static mut __stderrp: *mut FILE; } - unsafe { __stderrp() } + unsafe { __stderrp } } #[cfg(target_os = "openbsd")] From d0294cee268b4ad819eb0394591631fa859e752a Mon Sep 17 00:00:00 2001 From: Etienne Cordonnier Date: Mon, 19 Oct 2026 15:45:55 +0200 Subject: [PATCH 4/4] stdbuf: use libc constants for stdio fds in test --- src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs index 8584386c478..3875fa69fd6 100644 --- a/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs +++ b/src/uu/stdbuf/src/libstdbuf/src/libstdbuf.rs @@ -258,9 +258,9 @@ mod tests { #[test] fn test_stream_getters_return_matching_streams() { unsafe { - assert_eq!(fileno(__stdbuf_get_stdin()), 0); - assert_eq!(fileno(__stdbuf_get_stdout()), 1); - assert_eq!(fileno(__stdbuf_get_stderr()), 2); + assert_eq!(fileno(__stdbuf_get_stdin()), libc::STDIN_FILENO); + assert_eq!(fileno(__stdbuf_get_stdout()), libc::STDOUT_FILENO); + assert_eq!(fileno(__stdbuf_get_stderr()), libc::STDERR_FILENO); } } }