improve patch

This commit is contained in:
curious-rabbit
2026-05-17 20:35:00 +02:00
parent c96398c1bb
commit 7d18db23a7
3 changed files with 21 additions and 20 deletions
+7 -7
View File
@@ -1,15 +1,15 @@
# Unreleased
## Bugfixes
- Sanitize control characters and bidirectional override characters in filenames
when output goes to a terminal, and prefix paths starting with `-` with `./` to
prevent argument injection. Also reject placeholders as the executable in
`--exec`/`--exec-batch` (was previously checked only for `--exec-batch`).
- Handle invalid working directories gracefully when using `--full-path`, see #1900 (@Xavrir).
## Features
- Add `--ignore-parent` option to override `--no-ignore-parent`, see #1958 (@tmchow)
## Bugfixes
- Sanitize control characters and bidirectional override characters in filenames
when output goes to a terminal, to prevent terminal escape-sequence injection.
Also reject a placeholder as the executable for `--exec-batch`, while still
allowing it for `--exec`.
- Handle invalid working directories gracefully when using `--full-path`, see #1900 (@Xavrir).
# 10.4.2
## Bugfixes
+13 -12
View File
@@ -43,7 +43,7 @@ impl CommandSet {
mode: ExecutionMode::OneByOne,
commands: input
.into_iter()
.map(CommandTemplate::new)
.map(|args| CommandTemplate::new(args, ExecutionMode::OneByOne))
.collect::<Result<_>>()?,
})
}
@@ -59,7 +59,7 @@ impl CommandSet {
commands: input
.into_iter()
.map(|args| {
let cmd = CommandTemplate::new(args)?;
let cmd = CommandTemplate::new(args, ExecutionMode::Batch)?;
if cmd.number_of_tokens() > 1 {
bail!("Only one placeholder allowed for batch commands");
}
@@ -217,7 +217,7 @@ struct CommandTemplate {
}
impl CommandTemplate {
fn new<I, S>(input: I) -> Result<CommandTemplate>
fn new<I, S>(input: I, mode: ExecutionMode) -> Result<CommandTemplate>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
@@ -242,11 +242,10 @@ impl CommandTemplate {
bail!("No executable provided for --exec or --exec-batch");
}
// Reject placeholder-as-executable for both --exec and --exec-batch
// (was previously checked only for --exec-batch).
if args[0].has_tokens() {
// A placeholder as the executable is meaningful for `--exec` but never for `--exec-batch`.
if mode == ExecutionMode::Batch && args[0].has_tokens() {
bail!(
"First argument of --exec/--exec-batch must be a fixed executable, not a placeholder"
"First argument of --exec-batch must be a fixed executable, not a placeholder"
);
}
@@ -370,7 +369,8 @@ mod tests {
#[test]
fn tokens_with_literal_braces() {
let template = CommandTemplate::new(vec!["{{}}", "{{", "{.}}"]).unwrap();
let template =
CommandTemplate::new(vec!["{{}}", "{{", "{.}}"], ExecutionMode::OneByOne).unwrap();
assert_eq!(
generate_str(&template, "foo"),
vec!["{}", "{", "{.}", "foo"]
@@ -379,7 +379,8 @@ mod tests {
#[test]
fn tokens_with_literal_braces_and_placeholder() {
let template = CommandTemplate::new(vec!["echo", "{{{},end}"]).unwrap();
let template =
CommandTemplate::new(vec!["echo", "{{{},end}"], ExecutionMode::OneByOne).unwrap();
assert_eq!(generate_str(&template, "foo"), vec!["echo", "{foo,end}"]);
}
@@ -426,7 +427,7 @@ mod tests {
#[test]
fn template_no_args() {
assert!(CommandTemplate::new::<Vec<_>, &'static str>(vec![]).is_err());
assert!(CommandTemplate::new::<Vec<_>, &'static str>(vec![], ExecutionMode::OneByOne).is_err());
}
#[test]
@@ -436,8 +437,8 @@ mod tests {
#[test]
fn placeholder_as_executable_rejected() {
assert!(CommandSet::new(vec![vec!["{}"]]).is_err());
assert!(CommandSet::new(vec![vec!["{/}", "arg"]]).is_err());
assert!(CommandSet::new(vec![vec!["{}"]]).is_ok());
assert!(CommandSet::new(vec![vec!["{/}", "arg"]]).is_ok());
assert!(CommandSet::new_batch(vec![vec!["{}"]]).is_err());
}
+1 -1
View File
@@ -1906,7 +1906,7 @@ fn test_exec_batch() {
te.assert_failure_with_error(
&["foo", "--exec-batch", "echo {}"],
"error: First argument of --exec/--exec-batch must be a fixed executable, not a placeholder\n\
"error: First argument of --exec-batch must be a fixed executable, not a placeholder\n\
\n\
Usage: fd [OPTIONS] [pattern] [path]...\n\
\n\