Skip to content

Commit f7d3e18

Browse files
Merge #66
66: Fix argument tokenization r=matthiasbeyer a=matthiasbeyer The single and double quotes used to group words into a single command line argument must be trimmed from the tokens. E.g. the argument of `cmd "foo bar"` is the string `"foo bar"` and not `"\"foo bar\""`. Co-authored-by: Didier Wenzek <didier.wenzek@acidalie.com>
2 parents 33e7a3b + 2aa771b commit f7d3e18

File tree

3 files changed

+17
-12
lines changed

3 files changed

+17
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ readme = "README.md"
1414

1515

1616
[dependencies]
17+
comma = "1.0"
1718
nix = "0.14"
1819
regex = "1"
1920
tempfile = "3"

src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ pub enum Error {
3636

3737
#[error(transparent)]
3838
Regex(#[from] regex::Error),
39+
40+
#[error("The provided program arguments cannot be parsed")]
41+
BadProgramArguments,
3942
}

src/session.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -210,13 +210,8 @@ impl PtySession {
210210

211211
/// Turn e.g. "prog arg1 arg2" into ["prog", "arg1", "arg2"]
212212
/// Also takes care of single and double quotes
213-
fn tokenize_command(program: &str) -> Vec<String> {
214-
let re = Regex::new(r#""[^"]+"|'[^']+'|[^'" ]+"#).unwrap();
215-
let mut res = vec![];
216-
for cap in re.captures_iter(program) {
217-
res.push(cap[0].to_string());
218-
}
219-
res
213+
fn tokenize_command(program: &str) -> Result<Vec<String>, Error> {
214+
comma::parse_command(program).ok_or(Error::BadProgramArguments)
220215
}
221216

222217
/// Start command in background in a pty session (pty fork) and return a struct
@@ -237,7 +232,7 @@ pub fn spawn(program: &str, timeout_ms: Option<u64>) -> Result<PtySession, Error
237232
return Err(Error::EmptyProgramName);
238233
}
239234

240-
let mut parts = tokenize_command(program);
235+
let mut parts = tokenize_command(program)?;
241236
let prog = parts.remove(0);
242237
let mut command = Command::new(prog);
243238
command.args(parts);
@@ -579,15 +574,21 @@ mod tests {
579574
#[test]
580575
fn test_tokenize_command() {
581576
let res = tokenize_command("prog arg1 arg2");
582-
assert_eq!(vec!["prog", "arg1", "arg2"], res);
577+
assert_eq!(vec!["prog", "arg1", "arg2"], res.unwrap());
583578

584579
let res = tokenize_command("prog -k=v");
585-
assert_eq!(vec!["prog", "-k=v"], res);
580+
assert_eq!(vec!["prog", "-k=v"], res.unwrap());
586581

587582
let res = tokenize_command("prog 'my text'");
588-
assert_eq!(vec!["prog", "'my text'"], res);
583+
assert_eq!(vec!["prog", "my text"], res.unwrap());
589584

590585
let res = tokenize_command(r#"prog "my text""#);
591-
assert_eq!(vec!["prog", r#""my text""#], res);
586+
assert_eq!(vec!["prog", r#"my text"#], res.unwrap());
587+
588+
let res = tokenize_command(r#"prog "my text with quote'""#);
589+
assert_eq!(vec!["prog", r#"my text with quote'"#], res.unwrap());
590+
591+
let res = tokenize_command(r#"prog "my broken text"#);
592+
assert!(res.is_err());
592593
}
593594
}

0 commit comments

Comments
 (0)