Unwrap double-quoted Codex Bash commands
This commit is contained in:
1 parent
26fe9895e7
commit
cbdd8493ed
1 file changed
+40
-3
@@ -291,13 +291,16 @@ fn command_tool(item: &Value) -> (String, Value) {
|
|||||||
("Shell".to_string(), json!({"command": command}))
|
("Shell".to_string(), json!({"command": command}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// App-server renders the executor argv into one shell-quoted string. Unwrap only the exact Bash
|
/// App-server renders the executor argv into one shell-quoted string. Unwrap only an exact Bash
|
||||||
/// form Codex currently emits; anything with another argument or quoting form stays visible rather
|
/// invocation containing one shell word; extra arguments stay visible rather than being decoded
|
||||||
/// than being decoded into a command that was not actually run.
|
/// into a command that was not actually run.
|
||||||
fn rendered_bash_script(command: &str) -> Option<String> {
|
fn rendered_bash_script(command: &str) -> Option<String> {
|
||||||
let quoted = ["/usr/bin/bash -lc ", "/bin/bash -lc ", "bash -lc "]
|
let quoted = ["/usr/bin/bash -lc ", "/bin/bash -lc ", "bash -lc "]
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|prefix| command.strip_prefix(prefix))?;
|
.find_map(|prefix| command.strip_prefix(prefix))?;
|
||||||
|
if quoted.starts_with('"') {
|
||||||
|
return double_quoted_shell_word(quoted);
|
||||||
|
}
|
||||||
if !quoted.starts_with('\'') {
|
if !quoted.starts_with('\'') {
|
||||||
return (!quoted.is_empty() && !quoted.chars().any(char::is_whitespace))
|
return (!quoted.is_empty() && !quoted.chars().any(char::is_whitespace))
|
||||||
.then(|| quoted.to_string());
|
.then(|| quoted.to_string());
|
||||||
@@ -324,6 +327,26 @@ fn rendered_bash_script(command: &str) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn double_quoted_shell_word(quoted: &str) -> Option<String> {
|
||||||
|
let mut chars = quoted.strip_prefix('"')?.chars();
|
||||||
|
let mut script = String::new();
|
||||||
|
while let Some(character) = chars.next() {
|
||||||
|
match character {
|
||||||
|
'"' => return chars.next().is_none().then_some(script),
|
||||||
|
'\\' => match chars.next()? {
|
||||||
|
escaped @ ('$' | '`' | '"' | '\\') => script.push(escaped),
|
||||||
|
'\n' => {}
|
||||||
|
escaped => {
|
||||||
|
script.push('\\');
|
||||||
|
script.push(escaped);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
character => script.push(character),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn shell_word(word: &Value) -> String {
|
fn shell_word(word: &Value) -> String {
|
||||||
let Some(word) = word.as_str() else {
|
let Some(word) = word.as_str() else {
|
||||||
return word.to_string();
|
return word.to_string();
|
||||||
@@ -587,6 +610,20 @@ mod tests {
|
|||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let double_quoted = tool(&json!({
|
||||||
|
"id": "double-quoted",
|
||||||
|
"type": "commandExecution",
|
||||||
|
"command": r#"/usr/bin/bash -lc "printf '%s\\n' \"\$HOME\" \\path""#
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
double_quoted,
|
||||||
|
Some((
|
||||||
|
"double-quoted".to_string(),
|
||||||
|
"Bash".to_string(),
|
||||||
|
json!({"command": "printf '%s\\n' \"$HOME\" \\path"})
|
||||||
|
))
|
||||||
|
);
|
||||||
|
|
||||||
let fish = tool(&line(
|
let fish = tool(&line(
|
||||||
r#"{"id":"fish","type":"commandExecution","command":["/usr/bin/fish","-c","pwd"]}"#,
|
r#"{"id":"fish","type":"commandExecution","command":["/usr/bin/fish","-c","pwd"]}"#,
|
||||||
));
|
));
|
||||||
|
|||||||
Reference in new issue
Block a user