Shell-escape a value for embedding in a POSIX shell command. Wraps unsafe values in single quotes with the standard `'\''` idiom for embedded single-quote characters. Rejects null bytes which can truncate shell parsing at the C level.
(value: &str)
| 1463 | /// embedded single-quote characters. Rejects null bytes which can truncate |
| 1464 | /// shell parsing at the C level. |
| 1465 | fn shell_escape(value: &str) -> Result<String, String> { |
| 1466 | if value.bytes().any(|b| b == 0) { |
| 1467 | return Err("value contains null bytes".to_string()); |
| 1468 | } |
| 1469 | if value.bytes().any(|b| b == b'\n' || b == b'\r') { |
| 1470 | return Err("value contains newline or carriage return".to_string()); |
| 1471 | } |
| 1472 | if value.is_empty() { |
| 1473 | return Ok("''".to_string()); |
| 1474 | } |
| 1475 | let safe = value |
| 1476 | .bytes() |
| 1477 | .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'.' | b'/' | b'-' | b'_')); |
| 1478 | if safe { |
| 1479 | return Ok(value.to_string()); |
| 1480 | } |
| 1481 | let escaped = value.replace('\'', "'\"'\"'"); |
| 1482 | Ok(format!("'{escaped}'")) |
| 1483 | } |
| 1484 | |
| 1485 | /// Maximum total length of the assembled shell command string. |
| 1486 | const MAX_COMMAND_STRING_LEN: usize = 256 * 1024; // 256 KiB |
no test coverage detected