diff --git a/src/uu/env/src/env.rs b/src/uu/env/src/env.rs index 5e4b4fa18..7b36c7c63 100644 --- a/src/uu/env/src/env.rs +++ b/src/uu/env/src/env.rs @@ -3,7 +3,7 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. -// spell-checker:ignore (ToDO) chdir progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction Sigmask sigprocmask +// spell-checker:ignore (ToDO) chdir progname subcommand subcommands unsets setenv putenv spawnp SIGSEGV SIGBUS sigaction Sigmask sigprocmask elidable pub mod native_int_str; pub mod split_iterator; @@ -168,10 +168,6 @@ fn parse_signal_opt(target: &mut SignalRequest, opt: &OsStr) -> UResult<()> { if opt.is_empty() { return Ok(()); } - if opt == "__ALL__" { - target.apply_all = true; - return Ok(()); - } for sig in opt .as_bytes() @@ -193,7 +189,7 @@ fn parse_signal_opt(target: &mut SignalRequest, opt: &OsStr) -> UResult<()> { } #[cfg(unix)] -#[derive(Default)] +#[derive(Default, Debug)] struct SignalRequest { apply_all: bool, signals: BTreeSet, @@ -268,7 +264,11 @@ impl SignalActionLog { } #[cfg(unix)] -fn build_signal_request(matches: &clap::ArgMatches, option: &str) -> UResult { +fn build_signal_request( + matches: &clap::ArgMatches, + option: &str, + signal_apply_all: &BTreeSet<&str>, +) -> UResult { let mut request = SignalRequest::default(); let mut provided_values = 0usize; @@ -276,7 +276,9 @@ fn build_signal_request(matches: &clap::ArgMatches, option: &str) -> UResult(option) { for opt in iter { if opt.is_empty() { - explicit_empty = true; + if !signal_apply_all.contains(option) { + explicit_empty = true; + } continue; } provided_values += 1; @@ -538,6 +540,13 @@ struct EnvAppData { had_string_argument: bool, } +struct ParsedArguments { + original_args: Vec, + matches: clap::ArgMatches, + #[cfg(unix)] + signal_apply_all: BTreeSet<&'static str>, +} + impl EnvAppData { fn make_error_no_such_file_or_dir(&self, prog: &OsStr) -> Box { uucore::show_error!( @@ -634,17 +643,20 @@ impl EnvAppData { fn parse_arguments( &mut self, original_args: impl uucore::Args, - ) -> Result<(Vec, clap::ArgMatches), Box> { + ) -> Result> { let original_args: Vec = original_args.collect(); - let mut args = self.process_all_string_arguments(&original_args)?; + let args = self.process_all_string_arguments(&original_args)?; + #[cfg(unix)] + let mut signal_apply_all = BTreeSet::new(); - for arg in &mut args { + #[cfg(unix)] + for arg in &args { if arg == "--ignore-signal" { - *arg = OsString::from("--ignore-signal=__ALL__"); + signal_apply_all.insert(options::IGNORE_SIGNAL); } else if arg == "--default-signal" { - *arg = OsString::from("--default-signal=__ALL__"); + signal_apply_all.insert(options::DEFAULT_SIGNAL); } else if arg == "--block-signal" { - *arg = OsString::from("--block-signal=__ALL__"); + signal_apply_all.insert(options::BLOCK_SIGNAL); } } @@ -669,11 +681,21 @@ impl EnvAppData { } } }; - Ok((original_args, matches)) + Ok(ParsedArguments { + original_args, + matches, + #[cfg(unix)] + signal_apply_all, + }) } fn run_env(&mut self, original_args: impl uucore::Args) -> UResult<()> { - let (original_args, matches) = self.parse_arguments(original_args)?; + let ParsedArguments { + original_args, + matches, + #[cfg(unix)] + signal_apply_all, + } = self.parse_arguments(original_args)?; self.do_debug_printing = self.do_debug_printing || (0 != matches.get_count("debug")); self.do_input_debug_printing = self @@ -686,7 +708,11 @@ impl EnvAppData { } } - let mut opts = make_options(&matches)?; + let mut opts = make_options( + &matches, + #[cfg(unix)] + &signal_apply_all, + )?; apply_change_directory(&opts)?; @@ -888,7 +914,11 @@ fn apply_removal_of_all_env_vars(opts: &Options<'_>) { } } -fn make_options(matches: &clap::ArgMatches) -> UResult> { +#[cfg_attr(not(unix), allow(clippy::elidable_lifetime_names))] +fn make_options<'a>( + matches: &'a clap::ArgMatches, + #[cfg(unix)] signal_apply_all: &BTreeSet<&'static str>, +) -> UResult> { let ignore_env = matches.get_flag("ignore-environment"); let line_ending = LineEnding::from_zero_flag(matches.get_flag("null")); let running_directory = matches @@ -907,11 +937,11 @@ fn make_options(matches: &clap::ArgMatches) -> UResult> { .map(OsString::as_os_str); #[cfg(unix)] - let ignore_signal = build_signal_request(matches, options::IGNORE_SIGNAL)?; + let ignore_signal = build_signal_request(matches, options::IGNORE_SIGNAL, signal_apply_all)?; #[cfg(unix)] - let default_signal = build_signal_request(matches, options::DEFAULT_SIGNAL)?; + let default_signal = build_signal_request(matches, options::DEFAULT_SIGNAL, signal_apply_all)?; #[cfg(unix)] - let block_signal = build_signal_request(matches, options::BLOCK_SIGNAL)?; + let block_signal = build_signal_request(matches, options::BLOCK_SIGNAL, signal_apply_all)?; #[cfg(unix)] let list_signal_handling = matches.get_flag(options::LIST_SIGNAL_HANDLING); diff --git a/tests/by-util/test_env.rs b/tests/by-util/test_env.rs index cde3bccf4..4a989bd05 100644 --- a/tests/by-util/test_env.rs +++ b/tests/by-util/test_env.rs @@ -2009,3 +2009,22 @@ fn test_ignore_signal_pipe_broken_pipe_regression() { "With --ignore-signal=PIPE, process should exit gracefully (0 or 1), got: {ignore_signal_exit_code}" ); } + +#[test] +#[cfg(unix)] +fn test_env_disallow_double_underscore_all() { + new_ucmd!() + .args(&["--ignore-signal=__ALL__", "true"]) + .fails() + .stderr_contains("invalid signal"); + + new_ucmd!() + .args(&["--default-signal=__ALL__", "true"]) + .fails() + .stderr_contains("invalid signal"); + + new_ucmd!() + .args(&["--block-signal=__ALL__", "true"]) + .fails() + .stderr_contains("invalid signal"); +}