Fix quoted Bash tool titles
This commit is contained in:
1 parent
4c15150338
commit
f9c8f640ce
3 files changed
+67
-52
No files matched your search
@@ -292,59 +292,19 @@ fn command_tool(item: &Value) -> (String, Value) {
|
||||
}
|
||||
|
||||
/// App-server renders the executor argv into one shell-quoted string. Unwrap only an exact Bash
|
||||
/// invocation containing one shell word; extra arguments stay visible rather than being decoded
|
||||
/// into a command that was not actually run.
|
||||
/// invocation whose script has matching outer quotes; extra arguments stay visible rather than
|
||||
/// being mistaken for part of the script.
|
||||
fn rendered_bash_script(command: &str) -> Option<String> {
|
||||
let quoted = ["/usr/bin/bash -lc ", "/bin/bash -lc ", "bash -lc "]
|
||||
.iter()
|
||||
.find_map(|prefix| command.strip_prefix(prefix))?;
|
||||
if quoted.starts_with('"') {
|
||||
return double_quoted_shell_word(quoted);
|
||||
if quoted.len() >= 2
|
||||
&& ((quoted.starts_with('\'') && quoted.ends_with('\''))
|
||||
|| (quoted.starts_with('"') && quoted.ends_with('"')))
|
||||
{
|
||||
return Some(quoted[1..quoted.len() - 1].to_string());
|
||||
}
|
||||
if !quoted.starts_with('\'') {
|
||||
return (!quoted.is_empty() && !quoted.chars().any(char::is_whitespace))
|
||||
.then(|| quoted.to_string());
|
||||
}
|
||||
|
||||
let mut rest = quoted;
|
||||
let mut script = String::new();
|
||||
loop {
|
||||
rest = rest.strip_prefix('\'')?;
|
||||
let end = rest.find('\'')?;
|
||||
script.push_str(&rest[..end]);
|
||||
rest = &rest[end + 1..];
|
||||
if rest.is_empty() {
|
||||
return Some(script);
|
||||
}
|
||||
if let Some(after_quote) = rest.strip_prefix("\\'") {
|
||||
script.push('\'');
|
||||
rest = after_quote;
|
||||
} else {
|
||||
let after_quote = rest.strip_prefix("\"'\"")?;
|
||||
script.push('\'');
|
||||
rest = after_quote;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
(!quoted.is_empty() && !quoted.chars().any(char::is_whitespace)).then(|| quoted.to_string())
|
||||
}
|
||||
|
||||
fn shell_word(word: &Value) -> String {
|
||||
@@ -599,21 +559,21 @@ mod tests {
|
||||
let rendered = tool(&json!({
|
||||
"id": "rendered",
|
||||
"type": "commandExecution",
|
||||
"command": r#"/usr/bin/bash -lc 'printf '\''%s\n'\'' hello'"#
|
||||
"command": "/usr/bin/bash -lc 'printf \"%s\\n\" hello'"
|
||||
}));
|
||||
assert_eq!(
|
||||
rendered,
|
||||
Some((
|
||||
"rendered".to_string(),
|
||||
"Bash".to_string(),
|
||||
json!({"command": "printf '%s\\n' hello"})
|
||||
json!({"command": "printf \"%s\\n\" hello"})
|
||||
))
|
||||
);
|
||||
|
||||
let double_quoted = tool(&json!({
|
||||
"id": "double-quoted",
|
||||
"type": "commandExecution",
|
||||
"command": r#"/usr/bin/bash -lc "printf '%s\\n' \"\$HOME\" \\path""#
|
||||
"command": r#"/usr/bin/bash -lc "printf '%s\n' "$HOME" \path""#
|
||||
}));
|
||||
assert_eq!(
|
||||
double_quoted,
|
||||
|
||||
Reference in new issue
Block a user