(command: string)
| 386 | * @internal Exported for testing |
| 387 | */ |
| 388 | export function extractSedExpressions(command: string): string[] { |
| 389 | const expressions: string[] = [] |
| 390 | |
| 391 | // Calculate withoutSed by trimming off the first N characters (removing 'sed ') |
| 392 | const sedMatch = command.match(/^\s*sed\s+/) |
| 393 | if (!sedMatch) return expressions |
| 394 | |
| 395 | const withoutSed = command.slice(sedMatch[0].length) |
| 396 | |
| 397 | // Reject dangerous flag combinations like -ew, -eW, -ee, -we (combined -e/-w with dangerous commands) |
| 398 | if (/-e[wWe]/.test(withoutSed) || /-w[eE]/.test(withoutSed)) { |
| 399 | throw new Error('Dangerous flag combination detected') |
| 400 | } |
| 401 | |
| 402 | // Use shell-quote to parse the arguments properly |
| 403 | const parseResult = tryParseShellCommand(withoutSed) |
| 404 | if (!parseResult.success) { |
| 405 | // Malformed shell syntax - throw error to be caught by caller |
| 406 | throw new Error(`Malformed shell syntax: ${parseResult.error}`) |
| 407 | } |
| 408 | const parsed = parseResult.tokens |
| 409 | try { |
| 410 | let foundEFlag = false |
| 411 | let foundExpression = false |
| 412 | |
| 413 | for (let i = 0; i < parsed.length; i++) { |
| 414 | const arg = parsed[i] |
| 415 | |
| 416 | // Skip non-string arguments (like control operators) |
| 417 | if (typeof arg !== 'string') continue |
| 418 | |
| 419 | // Handle -e flag followed by expression |
| 420 | if ((arg === '-e' || arg === '--expression') && i + 1 < parsed.length) { |
| 421 | foundEFlag = true |
| 422 | const nextArg = parsed[i + 1] |
| 423 | if (typeof nextArg === 'string') { |
| 424 | expressions.push(nextArg) |
| 425 | i++ // Skip the next argument since we consumed it |
| 426 | } |
| 427 | continue |
| 428 | } |
| 429 | |
| 430 | // Handle --expression=value format |
| 431 | if (arg.startsWith('--expression=')) { |
| 432 | foundEFlag = true |
| 433 | expressions.push(arg.slice('--expression='.length)) |
| 434 | continue |
| 435 | } |
| 436 | |
| 437 | // Handle -e=value format (non-standard but defense in depth) |
| 438 | if (arg.startsWith('-e=')) { |
| 439 | foundEFlag = true |
| 440 | expressions.push(arg.slice('-e='.length)) |
| 441 | continue |
| 442 | } |
| 443 | |
| 444 | // Skip other flags |
| 445 | if (arg.startsWith('-')) continue |
no test coverage detected