Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,15 @@ struct Options<'a> {
fn print_env(line_ending: LineEnding) {
let stdout_raw = io::stdout();
let mut stdout = stdout_raw.lock();
for (n, v) in env::vars() {
write!(stdout, "{n}={v}{line_ending}").unwrap();
// vars_os in case we get some invalid strings
for (n, v) in env::vars_os() {
write!(
stdout,
"{}={}{line_ending}",
n.to_string_lossy(),
v.to_string_lossy()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's not correct because GNU env doesn't output a lossy string:

$ FOO=$'\xFF\xFE' env | hexdump -C
46 4f 4f 3d ff fe  // I omitted everything else

I don't know about the key, I wasn't able to create an env var whose key contains a non-utf8 char.

Copy link

@Leont Leont Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Environmental variables aren't necessarily the utf8-encoded strings we want them to be. They're null terminated binary strings (hopefully containing a = but I'm not even sure that is enforced). This is unfortunately the kind of place where that distinction matters.

)
.unwrap();
}
}

Expand Down
24 changes: 24 additions & 0 deletions tests/by-util/test_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,30 @@ fn disallow_equals_sign_on_short_unset_option() {
.stderr_contains("env: cannot unset '': Invalid argument");
}

#[test]
#[cfg(unix)]
fn test_non_utf8_env_var() {
// Test that env doesn't panic with non-UTF-8 environment variables
// https://bugs.launchpad.net/ubuntu/+source/rust-coreutils/+bug/2132941
use std::ffi::OsString;
use std::os::unix::ffi::OsStringExt;

let mut non_utf8_value = Vec::from(b"foo");
non_utf8_value.push(0xA0); // Invalid UTF-8 byte
let non_utf8_os_string = OsString::from_vec(non_utf8_value);

let result = new_ucmd!()
.env("FOO_NON_UTF8", non_utf8_os_string)
.succeeds();

assert!(
result
.stdout_str()
.lines()
.any(|line| line.starts_with("FOO_NON_UTF8=foo"))
);
}

#[cfg(test)]
mod tests_split_iterator {

Expand Down
Loading