mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
Fix printenv non-UTF8 (#9728)
* printenv: Handle invalid UTF-8 encoding in variables * test(printenv): Add test for non-UTF8 content in variable
This commit is contained in:
parent
b9b965555c
commit
0bfbbc00c7
2 changed files with 46 additions and 12 deletions
|
|
@ -3,10 +3,14 @@
|
|||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
use std::env;
|
||||
use uucore::translate;
|
||||
use uucore::{error::UResult, format_usage};
|
||||
use std::io::Write;
|
||||
|
||||
use clap::{Arg, ArgAction, Command};
|
||||
|
||||
use uucore::error::UResult;
|
||||
use uucore::line_ending::LineEnding;
|
||||
use uucore::{format_usage, os_str_as_bytes, translate};
|
||||
|
||||
static OPT_NULL: &str = "null";
|
||||
|
||||
|
|
@ -21,15 +25,16 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
.map(|v| v.map(ToString::to_string).collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
let separator = if matches.get_flag(OPT_NULL) {
|
||||
"\x00"
|
||||
} else {
|
||||
"\n"
|
||||
};
|
||||
let separator = LineEnding::from_zero_flag(matches.get_flag(OPT_NULL));
|
||||
|
||||
if variables.is_empty() {
|
||||
for (env_var, value) in env::vars() {
|
||||
print!("{env_var}={value}{separator}");
|
||||
for (env_var, value) in env::vars_os() {
|
||||
let env_bytes = os_str_as_bytes(&env_var)?;
|
||||
let val_bytes = os_str_as_bytes(&value)?;
|
||||
std::io::stdout().lock().write_all(env_bytes)?;
|
||||
print!("=");
|
||||
std::io::stdout().lock().write_all(val_bytes)?;
|
||||
print!("{separator}");
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
|
@ -41,8 +46,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
error_found = true;
|
||||
continue;
|
||||
}
|
||||
if let Ok(var) = env::var(env_var) {
|
||||
print!("{var}{separator}");
|
||||
if let Some(var) = env::var_os(env_var) {
|
||||
let val_bytes = os_str_as_bytes(&var)?;
|
||||
std::io::stdout().lock().write_all(val_bytes)?;
|
||||
print!("{separator}");
|
||||
} else {
|
||||
error_found = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,3 +90,30 @@ fn test_null_separator() {
|
|||
.stdout_is("FOO\x00VALUE\x00");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
#[cfg(not(any(target_os = "freebsd", target_os = "android", target_os = "openbsd")))]
|
||||
fn test_non_utf8_value() {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
// Environment variable values can contain non-UTF-8 bytes on Unix.
|
||||
// printenv should output them correctly, matching GNU behavior.
|
||||
// Reproduces: LD_PRELOAD=$'/tmp/lib.so\xff' printenv LD_PRELOAD
|
||||
let value_with_invalid_utf8 = OsStr::from_bytes(b"/tmp/lib.so\xff");
|
||||
|
||||
let result = new_ucmd!()
|
||||
.env("LD_PRELOAD", value_with_invalid_utf8)
|
||||
.arg("LD_PRELOAD")
|
||||
.run();
|
||||
|
||||
// Use byte-based assertions to avoid UTF-8 conversion issues
|
||||
// when the test framework tries to format error messages
|
||||
assert!(
|
||||
result.succeeded(),
|
||||
"Command failed with exit code: {:?}, stderr: {:?}",
|
||||
result.code(),
|
||||
String::from_utf8_lossy(result.stderr())
|
||||
);
|
||||
result.stdout_is_bytes(b"/tmp/lib.so\xff\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue