context: run commands in the C locale by default

Subprocesses inherit the session environment, so a translated host
locale leaked into builds: perl-based packaging tools
(dpkg-architecture, dpkg-parsechangelog, quilt, ...) warned about
missing locale settings, change their output with the environment,
and dpkg-buildpackage treats some of that output as data.

Default every command to LANG=C and LC_ALL=C; a caller can still
override explicitly through envs().
This commit is contained in:
2026-09-20 19:06:04 +02:00
parent 5592d5a6e4
commit 31fe6dc524
+38 -1
View File
@@ -243,12 +243,22 @@ impl Context {
}
/// Make a command inside context
///
/// Build tooling must not inherit the session's locale: dpkg-family
/// tools and perl-based packaging scripts change their output (and
/// dpkg-buildpackage treats some of it as data) with the environment,
/// and a translated or mixed locale leaks host state into builds. The
/// C locale is the default; a caller can still override it by setting
/// LANG/LC_ALL through [`ContextCommand::envs`] afterwards.
pub fn command<S: AsRef<OsStr>>(&self, program: S) -> ContextCommand<'_> {
ContextCommand {
context: self,
program: program.as_ref().to_string_lossy().to_string(),
args: Vec::new(),
env: Vec::new(),
env: vec![
("LANG".to_string(), "C".to_string()),
("LC_ALL".to_string(), "C".to_string()),
],
cwd: None,
sink: None,
}
@@ -530,4 +540,31 @@ mod endpoint_tests {
let err = ContextConfig::from_endpoint("host:99999").unwrap_err();
assert_eq!(err, "Invalid port number");
}
/// Commands run in the C locale whatever the session environment
/// carries: host locale variables must not leak into builds. An
/// explicit caller override still wins.
#[test]
fn commands_default_to_the_c_locale() {
let ctx = Context::new(ContextConfig::Local).unwrap();
let locale = ctx
.command("sh")
.arg("-c")
.arg("printf '%s' \"${LC_ALL:-unset}:${LANG:-unset}\"")
.output()
.unwrap()
.stdout;
assert_eq!(String::from_utf8_lossy(&locale), "C:C");
let locale = ctx
.command("sh")
.arg("-c")
.arg("printf '%s' \"$LC_ALL\"")
.env("LC_ALL", "C.UTF-8")
.output()
.unwrap()
.stdout;
assert_eq!(String::from_utf8_lossy(&locale), "C.UTF-8");
}
}