@shipfox/expression 1.2.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +25 -12
  2. package/dist/expression/create-workflow-expression.d.ts.map +1 -1
  3. package/dist/expression/create-workflow-expression.js +5 -0
  4. package/dist/expression/create-workflow-expression.js.map +1 -1
  5. package/dist/index.d.ts +4 -3
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/plan/context-key-access.d.ts +2 -0
  10. package/dist/plan/context-key-access.d.ts.map +1 -1
  11. package/dist/plan/context-key-access.js +3 -0
  12. package/dist/plan/context-key-access.js.map +1 -1
  13. package/dist/plan/evaluate-planned-predicate.d.ts.map +1 -1
  14. package/dist/plan/evaluate-planned-predicate.js +2 -2
  15. package/dist/plan/evaluate-planned-predicate.js.map +1 -1
  16. package/dist/run/hoist-run-command.d.ts +8 -0
  17. package/dist/run/hoist-run-command.d.ts.map +1 -1
  18. package/dist/run/hoist-run-command.js +28 -3
  19. package/dist/run/hoist-run-command.js.map +1 -1
  20. package/dist/run/shell-code-position.d.ts +21 -0
  21. package/dist/run/shell-code-position.d.ts.map +1 -0
  22. package/dist/run/shell-code-position.js +623 -0
  23. package/dist/run/shell-code-position.js.map +1 -0
  24. package/dist/run/shell-quoting.d.ts +5 -1
  25. package/dist/run/shell-quoting.d.ts.map +1 -1
  26. package/dist/run/shell-quoting.js +37 -6
  27. package/dist/run/shell-quoting.js.map +1 -1
  28. package/dist/tsconfig.test.tsbuildinfo +1 -1
  29. package/dist/workflow-context/workflow-context-docs.d.ts +185 -0
  30. package/dist/workflow-context/workflow-context-docs.d.ts.map +1 -0
  31. package/dist/workflow-context/workflow-context-docs.js +168 -0
  32. package/dist/workflow-context/workflow-context-docs.js.map +1 -0
  33. package/dist/workflow-context/workflow-context.d.ts +99 -114
  34. package/dist/workflow-context/workflow-context.d.ts.map +1 -1
  35. package/dist/workflow-context/workflow-context.js +201 -85
  36. package/dist/workflow-context/workflow-context.js.map +1 -1
  37. package/package.json +2 -2
  38. package/dist/template/extract-cel-untrusted-path-accesses.d.ts +0 -5
  39. package/dist/template/extract-cel-untrusted-path-accesses.d.ts.map +0 -1
  40. package/dist/template/extract-cel-untrusted-path-accesses.js +0 -140
  41. package/dist/template/extract-cel-untrusted-path-accesses.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/run/shell-code-position.ts"],"sourcesContent":["import {\n classifyShellSite,\n initialShellScanState,\n type ShellScanState,\n type ShellSiteContext,\n scanShellLiteral,\n} from './shell-quoting.js';\n\nconst shellIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\nconst shellIdentifierStartPattern = /[A-Za-z_]/;\nconst shellIdentifierCharacterPattern = /[A-Za-z0-9_]/;\nconst shellAssignmentPattern = /^[A-Za-z_][A-Za-z0-9_]*=/;\nconst shellDigitPattern = /[0-9]/;\nconst shellRedirectionCharacterPattern = /[<>]/;\nconst shellSedFlagPattern = /^-[neiErzbsu]+$/;\nconst shellWhitespacePattern = /\\s/;\nconst shellCompoundArithmeticAssignmentPattern =\n /^[A-Za-z_][A-Za-z0-9_]*\\s*(?:\\+=|-=|\\*=|\\/=|%=|<<=|>>=|&=|\\|=|\\^=)/;\n\nconst shellReservedPrefixWords = new Set([\n 'case',\n 'do',\n 'done',\n 'elif',\n 'else',\n 'fi',\n 'for',\n 'if',\n 'in',\n 'then',\n 'time',\n 'until',\n 'while',\n '!',\n]);\n\nconst shellCommandWrapperWords = new Set(['command', 'env', 'nohup', 'sudo']);\n\nexport type ShellReevaluatingConstruct =\n | 'eval'\n | 'sh-c'\n | 'bash-c'\n | 'source'\n | 'let'\n | 'declare-i'\n | 'arithmetic'\n | 'awk'\n | 'jq'\n | 'sed'\n | 'xargs-sh-c';\n\nexport interface ShellCodePositionMatch {\n readonly construct: ShellReevaluatingConstruct;\n readonly name: string;\n}\n\nexport interface ShellCodePositionAnalysis {\n readonly matches: readonly ShellCodePositionMatch[];\n}\n\ninterface ShellVariableReference {\n readonly kind: 'direct' | 'arithmetic';\n readonly isSingleQuotedLiteral: boolean;\n readonly name: string;\n}\n\ninterface ShellWord {\n readonly dynamic: boolean;\n readonly kind: 'word';\n readonly isRedirectionTarget: boolean;\n readonly references: readonly ShellVariableReference[];\n readonly value: string;\n}\n\ninterface MutableShellWord {\n readonly isRedirectionTarget: boolean;\n readonly references: ShellVariableReference[];\n readonly value: string[];\n dynamic: boolean;\n}\n\ninterface ShellControl {\n readonly kind: 'control';\n}\n\ninterface ShellRedirection {\n readonly kind: 'redirection';\n}\n\ntype ShellToken = ShellWord | ShellControl | ShellRedirection;\n\n/**\n * Finds workflow-controlled values that are passed to shell constructs which\n * deliberately parse or evaluate their arguments again.\n *\n * The scanner follows direct references in a single shell word only. It does\n * not attempt shell data-flow analysis, and intentionally prefers a missed\n * warning over a false positive.\n */\nexport function classifyShellCodePosition(params: {\n readonly command: string;\n readonly workflowDataNames: Iterable<string>;\n}): ShellCodePositionAnalysis {\n const workflowDataNames = new Set(params.workflowDataNames);\n const matches: ShellCodePositionMatch[] = [];\n\n if (workflowDataNames.size === 0) return {matches: []};\n\n const tokens = tokenizeShell(params.command);\n let command: ShellWord[] = [];\n\n const report = (reference: ShellVariableReference, construct: ShellReevaluatingConstruct) => {\n if (!workflowDataNames.has(reference.name)) return;\n\n matches.push({construct, name: reference.name});\n };\n\n const reportReferences = (\n words: readonly ShellWord[],\n construct: ShellReevaluatingConstruct,\n kinds: readonly ShellVariableReference['kind'][] = ['direct'],\n includeSingleQuotedLiterals = false,\n ) => {\n for (const word of words) {\n for (const reference of word.references) {\n if (\n kinds.includes(reference.kind) &&\n (includeSingleQuotedLiterals || !reference.isSingleQuotedLiteral)\n ) {\n report(reference, construct);\n }\n }\n }\n };\n\n const analyzeCommand = (words: readonly ShellWord[]) => {\n const commandWords = words.filter((word) => !word.isRedirectionTarget);\n const firstWord = commandWords[0];\n if (firstWord !== undefined && shellWordIsStatic(firstWord) && firstWord.value === 'for') {\n return;\n }\n const headIndex = commandHeadIndex(commandWords);\n const head = commandWords[headIndex];\n if (head === undefined || !shellWordIsStatic(head)) return;\n\n const commandName = shellCommandName(head.value);\n if (commandName === undefined) return;\n\n const argumentWords = commandWords.slice(headIndex + 1);\n\n if (commandName === 'eval') {\n reportReferences(argumentWords, 'eval', ['direct'], true);\n return;\n }\n\n if (commandName === 'sh' || commandName === 'bash') {\n const program = shellProgramAfterC(argumentWords);\n if (program !== undefined) {\n reportReferences([program], commandName === 'sh' ? 'sh-c' : 'bash-c');\n }\n return;\n }\n\n if (commandName === 'source' || commandName === '.') {\n reportReferences(argumentWords.slice(0, 1), 'source');\n return;\n }\n\n if (commandName === 'let') {\n reportReferences(argumentWords, 'let');\n reportBareArithmeticReferences(argumentWords, 'let', report, workflowDataNames, false);\n return;\n }\n\n if (commandName === 'declare' && argumentWords.some((word) => word.value === '-i')) {\n reportReferences(argumentWords, 'declare-i');\n reportBareArithmeticReferences(argumentWords, 'declare-i', report, workflowDataNames, true);\n return;\n }\n\n if (commandName === 'awk' || commandName === 'jq' || commandName === 'sed') {\n const program = interpreterProgramWord(commandName, argumentWords);\n if (program !== undefined) reportReferences([program], commandName);\n return;\n }\n\n if (commandName === 'xargs') {\n const nestedShell = xargsShellProgram(argumentWords);\n if (nestedShell !== undefined) {\n reportReferences([nestedShell.program], 'xargs-sh-c');\n }\n }\n };\n\n for (const token of tokens) {\n if (token.kind === 'control') {\n analyzeCommand(command);\n command = [];\n continue;\n }\n\n if (\n token.kind === 'word' &&\n token.references.some((reference) => reference.kind === 'arithmetic')\n ) {\n reportReferences([token], 'arithmetic', ['arithmetic']);\n }\n\n if (token.kind === 'word') command.push(token);\n }\n\n analyzeCommand(command);\n\n return {matches};\n}\n\nfunction tokenizeShell(source: string): readonly ShellToken[] {\n const tokens: ShellToken[] = [];\n let current: MutableShellWord | undefined;\n let index = 0;\n let redirectionTarget = false;\n let wordCanStartComment = true;\n let scanState: ShellScanState = initialShellScanState;\n let arithmeticContext = false;\n let parameterBracketDepth = 0;\n let arithmeticBracketDepth = 0;\n let arithmeticShellSyntax = false;\n\n function ensureWord(): MutableShellWord {\n if (current !== undefined) return current;\n current = {\n dynamic: false,\n isRedirectionTarget: redirectionTarget,\n references: [],\n value: [],\n };\n redirectionTarget = false;\n wordCanStartComment = false;\n return current;\n }\n\n function flushWord(): void {\n if (current === undefined) return;\n tokens.push({\n dynamic: current.dynamic,\n kind: 'word',\n isRedirectionTarget: current.isRedirectionTarget,\n references: current.references.filter(\n (reference) => !(arithmeticShellSyntax && reference.kind === 'arithmetic'),\n ),\n value: current.value.join(''),\n });\n current = undefined;\n arithmeticShellSyntax = false;\n }\n\n function markDynamic(): void {\n ensureWord().dynamic = true;\n }\n\n function addReference(\n name: string,\n kind: ShellVariableReference['kind'],\n isSingleQuotedLiteral = false,\n ): void {\n if (kind === 'arithmetic' && arithmeticShellSyntax) return;\n ensureWord().references.push({kind, isSingleQuotedLiteral, name});\n }\n\n function markArithmeticShellSyntax(): void {\n arithmeticShellSyntax = true;\n }\n\n function advance(text: string): void {\n scanState = scanShellLiteral(text, scanState);\n index += text.length;\n\n const site = classifyShellSite(scanState);\n if (arithmeticContext && !(site.kind === 'unsafe' && site.region === 'arith')) {\n arithmeticContext = false;\n arithmeticBracketDepth = 0;\n }\n }\n\n function advanceEscape(): void {\n const nextCharacter = source[index + 1];\n if (nextCharacter === undefined) {\n advance(source[index] ?? '');\n return;\n }\n\n if (nextCharacter !== '\\n') ensureWord().value.push(nextCharacter);\n advance(source.slice(index, index + 2));\n }\n\n function advanceExpansion(\n kind: ShellVariableReference['kind'],\n isSingleQuotedLiteral = false,\n ): boolean {\n if (source[index] !== '$') return false;\n\n if (source.startsWith('$((', index)) {\n markDynamic();\n arithmeticContext = true;\n advance('$((');\n return true;\n }\n\n if (source.startsWith('$[', index)) {\n markDynamic();\n arithmeticContext = true;\n advance('$[');\n return true;\n }\n\n if (source.startsWith('$(', index)) {\n markDynamic();\n advance('$(');\n return true;\n }\n\n if (source.startsWith('${', index)) {\n markDynamic();\n const firstName = readParameterName(source, index + 2);\n if (source[index + 2] !== '#' && firstName !== undefined) {\n addReference(firstName.value, kind, isSingleQuotedLiteral);\n }\n advance('${');\n return true;\n }\n\n if (source.startsWith(\"$'\", index) || source.startsWith('$\"', index)) {\n markDynamic();\n advance(source.slice(index, index + 2));\n return true;\n }\n\n const name = readShellIdentifier(source, index + 1);\n if (name === undefined) return false;\n\n addReference(name.value, kind, isSingleQuotedLiteral);\n advance(source.slice(index, name.index));\n return true;\n }\n\n while (index < source.length) {\n const character = source[index];\n if (character === undefined) break;\n\n const site = classifyShellSite(scanState);\n if (site.kind === 'unsafe') {\n if (site.region === 'line-comment') {\n if (character === '\\n') {\n advance('\\n');\n flushWord();\n tokens.push({kind: 'control'});\n wordCanStartComment = true;\n redirectionTarget = false;\n } else {\n advance(character);\n }\n continue;\n }\n\n if (site.region === 'heredoc') {\n advance(character);\n continue;\n }\n\n if (site.region === 'arith') {\n if (character === '[') arithmeticBracketDepth += 1;\n if (character === ']' && arithmeticBracketDepth > 0) arithmeticBracketDepth -= 1;\n if (\n arithmeticBracketDepth === 0 &&\n (character === \"'\" || character === '\"' || character === '`')\n ) {\n markArithmeticShellSyntax();\n }\n\n if (advanceExpansion('arithmetic')) continue;\n\n const name = readShellIdentifier(source, index);\n if (name !== undefined) {\n const nextIndex = skipWhitespace(source, name.index);\n if (!isArithmeticAssignment(source, nextIndex)) addReference(name.value, 'arithmetic');\n advance(source.slice(index, name.index));\n continue;\n }\n } else if (site.region === 'param-brace') {\n if (character === '[') parameterBracketDepth += 1;\n if (character === ']' && parameterBracketDepth > 0) parameterBracketDepth -= 1;\n\n const referenceKind =\n arithmeticContext || parameterBracketDepth > 0 ? 'arithmetic' : 'direct';\n if (advanceExpansion(referenceKind)) continue;\n } else {\n markDynamic();\n }\n\n const chunk = scannerChunkAt(source, index, site);\n advance(chunk);\n continue;\n }\n\n if (character === '\\\\') {\n advanceEscape();\n continue;\n }\n\n if (character === '#' && wordCanStartComment) {\n advance('#');\n continue;\n }\n\n if (character === '$' && advanceExpansion('direct', site.kind === 'single')) continue;\n\n if (character === '`') {\n markDynamic();\n advance('`');\n continue;\n }\n\n if (site.kind === 'unquoted' && isShellWhitespace(character)) {\n flushWord();\n if (character === '\\n') tokens.push({kind: 'control'});\n wordCanStartComment = true;\n if (character === '\\n') redirectionTarget = false;\n advance(character);\n continue;\n }\n\n if (character === \"'\" || character === '\"') {\n ensureWord();\n advance(character);\n continue;\n }\n\n if (site.kind === 'unquoted' && startsShellRedirection(source, index)) {\n flushWord();\n tokens.push({kind: 'redirection'});\n redirectionTarget = true;\n wordCanStartComment = true;\n const length = shellRedirectionLength(source, index);\n advance(source.slice(index, index + length));\n continue;\n }\n\n if (site.kind === 'unquoted' && startsShellArithmetic(source, index)) {\n markDynamic();\n arithmeticContext = true;\n advance('((');\n continue;\n }\n\n if (site.kind === 'unquoted' && startsShellControl(source, index)) {\n flushWord();\n tokens.push({kind: 'control'});\n wordCanStartComment = true;\n redirectionTarget = false;\n advance(source.slice(index, index + shellControlLength(source, index)));\n continue;\n }\n\n ensureWord().value.push(character);\n advance(character);\n }\n\n flushWord();\n return tokens;\n}\n\nfunction scannerChunkAt(\n source: string,\n index: number,\n site: Extract<ShellSiteContext, {kind: 'unsafe'}>,\n): string {\n if (site.region === 'arith' && source[index] === ')') {\n let closingRunLength = 0;\n while (source[index + closingRunLength] === ')') closingRunLength += 1;\n if (closingRunLength > 2) return ')'.repeat(closingRunLength - 2);\n if (closingRunLength === 2) return '))';\n return ')';\n }\n if (source.startsWith('$((', index)) return '$((';\n if (source.startsWith('((', index)) return '((';\n if (source.startsWith('$[', index)) return '$[';\n if (source.startsWith('$(', index) || source.startsWith('${', index))\n return source.slice(index, index + 2);\n if (source.startsWith('<<-', index)) return '<<-';\n if (source.startsWith('<<', index)) return '<<';\n if (source[index] === '\\\\' && index + 1 < source.length) return source.slice(index, index + 2);\n return source[index] ?? '';\n}\n\nfunction commandHeadIndex(words: readonly ShellWord[]): number {\n let index = 0;\n while (index < words.length) {\n const word = words[index];\n if (isShellAssignment(word)) {\n index += 1;\n continue;\n }\n if (word !== undefined && shellWordIsStatic(word) && shellReservedPrefixWords.has(word.value)) {\n index += 1;\n continue;\n }\n if (word !== undefined && shellWordIsStatic(word) && shellCommandWrapperWords.has(word.value)) {\n index += 1;\n continue;\n }\n break;\n }\n return index;\n}\n\nfunction shellWordIsStatic(word: ShellWord): boolean {\n return !word.dynamic && word.references.length === 0;\n}\n\nfunction shellCommandName(value: string): string | undefined {\n if (value.length === 0) return undefined;\n const name = value.split('/').at(-1);\n return name === undefined || (!shellIdentifierPattern.test(name) && name !== '.')\n ? undefined\n : name;\n}\n\nfunction shellProgramAfterC(words: readonly ShellWord[]): ShellWord | undefined {\n for (let index = 0; index < words.length; index += 1) {\n const word = words[index];\n if (word?.value === '-c' || word?.value === '--command') return words[index + 1];\n if (word?.value.startsWith('-') && !word.value.startsWith('--') && word.value.includes('c')) {\n return words[index + 1];\n }\n if (word?.value === '--') return undefined;\n }\n return undefined;\n}\n\nfunction reportBareArithmeticReferences(\n words: readonly ShellWord[],\n construct: 'let' | 'declare-i',\n report: (reference: ShellVariableReference, construct: ShellReevaluatingConstruct) => void,\n workflowDataNames: ReadonlySet<string>,\n skipDeclarationNames: boolean,\n): void {\n for (const word of words) {\n if (word.references.length > 0 || word.value.startsWith('-')) continue;\n const expression = skipDeclarationNames ? declarationExpression(word.value) : word.value;\n if (expression === undefined) continue;\n\n for (const identifier of arithmeticIdentifiers(expression)) {\n if (workflowDataNames.has(identifier)) {\n report({kind: 'arithmetic', name: identifier, isSingleQuotedLiteral: false}, construct);\n }\n }\n }\n}\n\nfunction declarationExpression(value: string): string | undefined {\n if (shellIdentifierPattern.test(value)) return undefined;\n if (shellCompoundArithmeticAssignmentPattern.test(value)) {\n return value;\n }\n const assignmentIndex = value.indexOf('=');\n if (assignmentIndex < 0) return undefined;\n return value.slice(assignmentIndex + 1);\n}\n\nfunction arithmeticIdentifiers(source: string): readonly string[] {\n const identifiers: string[] = [];\n let index = 0;\n while (index < source.length) {\n const name = readShellIdentifier(source, index);\n if (name === undefined) {\n index += 1;\n continue;\n }\n\n const nextIndex = skipWhitespace(source, name.index);\n if (!isArithmeticAssignment(source, nextIndex)) identifiers.push(name.value);\n index = name.index;\n }\n return identifiers;\n}\n\nfunction isArithmeticAssignment(source: string, index: number): boolean {\n return source[index] === '=' && source[index + 1] !== '=';\n}\n\nfunction interpreterProgramWord(\n command: 'awk' | 'jq' | 'sed',\n words: readonly ShellWord[],\n): ShellWord | undefined {\n let index = 0;\n while (index < words.length) {\n const word = words[index];\n if (word === undefined) return undefined;\n const value = word.value;\n\n if (value === '--') return words[index + 1];\n if (!value.startsWith('-') || value === '-') return word;\n\n if (command === 'jq' && jqOptionConsumesArguments(value)) {\n index += 3;\n continue;\n }\n\n if (command === 'awk' && awkOptionConsumesArgument(value)) {\n index += 2;\n continue;\n }\n\n if (command === 'awk' && (value === '-e' || value === '--source')) {\n return words[index + 1];\n }\n\n if (command === 'sed' && (value === '-e' || value === '--expression')) {\n return words[index + 1];\n }\n\n if (command === 'sed' && sedOptionConsumesArgument(value)) {\n index += 2;\n continue;\n }\n\n if (command === 'sed' && value.startsWith('--expression=')) return word;\n if (command === 'sed' && value.startsWith('--file=')) {\n index += 1;\n continue;\n }\n\n if (command === 'jq' && jqFlag(value)) {\n index += 1;\n continue;\n }\n\n if (command === 'awk' && awkFlag(value)) {\n index += 1;\n continue;\n }\n\n if (command === 'sed' && sedFlag(value)) {\n index += 1;\n continue;\n }\n\n return undefined;\n }\n return undefined;\n}\n\nfunction jqOptionConsumesArguments(value: string): boolean {\n return (\n value === '--arg' ||\n value === '--argjson' ||\n value === '--argfile' ||\n value === '--slurpfile' ||\n value === '--rawfile'\n );\n}\n\nfunction awkOptionConsumesArgument(value: string): boolean {\n return (\n value === '-f' ||\n value === '-v' ||\n value === '-F' ||\n value === '--assign' ||\n value === '--field-separator'\n );\n}\n\nfunction sedOptionConsumesArgument(value: string): boolean {\n return value === '-f' || value === '--file';\n}\n\nfunction jqFlag(value: string): boolean {\n return new Set([\n '-c',\n '-e',\n '-j',\n '-M',\n '-n',\n '-r',\n '-s',\n '-S',\n '-C',\n '--ascii-output',\n '--compact-output',\n '--exit-status',\n '--join-output',\n '--monochrome-output',\n '--null-input',\n '--raw-output',\n '--sort-keys',\n '--slurp',\n '--tab',\n '--version',\n ]).has(value);\n}\n\nfunction awkFlag(value: string): boolean {\n return (\n value === '--posix' || value === '--traditional' || value === '--lint' || value === '--sandbox'\n );\n}\n\nfunction sedFlag(value: string): boolean {\n return (\n shellSedFlagPattern.test(value) ||\n value === '--posix' ||\n value === '--regexp-extended' ||\n value === '--in-place'\n );\n}\n\nfunction xargsShellProgram(words: readonly ShellWord[]): {readonly program: ShellWord} | undefined {\n let index = 0;\n while (index < words.length) {\n const word = words[index];\n if (word === undefined) return undefined;\n const value = word.value;\n if (value === '--') {\n index += 1;\n break;\n }\n if (!value.startsWith('-') || value === '-') break;\n if (xargsOptionConsumesArgument(value)) index += 2;\n else index += 1;\n }\n\n const shell = words[index];\n if (shell === undefined || !shellWordIsStatic(shell)) return undefined;\n const shellName = shellCommandName(shell.value);\n if (shellName !== 'sh' && shellName !== 'bash') return undefined;\n\n const program = shellProgramAfterC(words.slice(index + 1));\n return program === undefined ? undefined : {program};\n}\n\nfunction xargsOptionConsumesArgument(value: string): boolean {\n return (\n value === '-d' ||\n value === '-E' ||\n value === '-I' ||\n value === '-J' ||\n value === '-L' ||\n value === '-n' ||\n value === '-P' ||\n value === '-s' ||\n value === '--delimiter' ||\n value === '--eof' ||\n value === '--max-args' ||\n value === '--max-lines' ||\n value === '--max-procs' ||\n value === '--max-chars' ||\n value === '--replace'\n );\n}\n\nfunction isShellAssignment(word: ShellWord | undefined): boolean {\n return word !== undefined && shellAssignmentPattern.test(word.value);\n}\n\nfunction readParameterName(\n source: string,\n start: number,\n): {readonly index: number; readonly value: string} | undefined {\n const prefix = source[start];\n return readShellIdentifier(source, prefix === '!' || prefix === '#' ? start + 1 : start);\n}\n\nfunction readShellIdentifier(\n source: string,\n start: number,\n): {readonly index: number; readonly value: string} | undefined {\n if (!shellIdentifierStartPattern.test(source[start] ?? '')) return undefined;\n let index = start + 1;\n while (shellIdentifierCharacterPattern.test(source[index] ?? '')) index += 1;\n return {index, value: source.slice(start, index)};\n}\n\nfunction skipWhitespace(source: string, start: number): number {\n let index = start;\n while (shellWhitespacePattern.test(source[index] ?? '')) index += 1;\n return index;\n}\n\nfunction isShellWhitespace(character: string): boolean {\n return character === ' ' || character === '\\t' || character === '\\r' || character === '\\n';\n}\n\nfunction startsShellRedirection(source: string, index: number): boolean {\n if (source[index] === '>' || source[index] === '<') return true;\n return (\n shellDigitPattern.test(source[index] ?? '') &&\n shellRedirectionCharacterPattern.test(source[index + 1] ?? '')\n );\n}\n\nfunction shellRedirectionLength(source: string, index: number): number {\n let nextIndex = index;\n while (shellDigitPattern.test(source[nextIndex] ?? '')) nextIndex += 1;\n if (source.startsWith('<<<', nextIndex)) return nextIndex - index + 3;\n if (source.startsWith('<<-', nextIndex)) return nextIndex - index + 3;\n if (source.startsWith('<<', nextIndex)) return nextIndex - index + 2;\n if (\n source.startsWith('>>', nextIndex) ||\n source.startsWith('<>', nextIndex) ||\n source.startsWith('>&', nextIndex) ||\n source.startsWith('<&', nextIndex) ||\n source.startsWith('>|', nextIndex)\n ) {\n return nextIndex - index + 2;\n }\n return nextIndex - index + 1;\n}\n\nfunction startsShellArithmetic(source: string, index: number): boolean {\n return source.startsWith('((', index);\n}\n\nfunction startsShellControl(source: string, index: number): boolean {\n return (\n source[index] === ';' ||\n source[index] === '&' ||\n source[index] === '|' ||\n source[index] === '(' ||\n source[index] === ')' ||\n source[index] === '{' ||\n source[index] === '}'\n );\n}\n\nfunction shellControlLength(source: string, index: number): number {\n if (\n source.startsWith('&&', index) ||\n source.startsWith('||', index) ||\n source.startsWith(';;', index) ||\n source.startsWith(';&', index) ||\n source.startsWith(';;&', index) ||\n source.startsWith('|&', index)\n ) {\n return source.startsWith(';;&', index) ? 3 : 2;\n }\n return 1;\n}\n"],"names":["classifyShellSite","initialShellScanState","scanShellLiteral","shellIdentifierPattern","shellIdentifierStartPattern","shellIdentifierCharacterPattern","shellAssignmentPattern","shellDigitPattern","shellRedirectionCharacterPattern","shellSedFlagPattern","shellWhitespacePattern","shellCompoundArithmeticAssignmentPattern","shellReservedPrefixWords","Set","shellCommandWrapperWords","classifyShellCodePosition","params","workflowDataNames","matches","size","tokens","tokenizeShell","command","report","reference","construct","has","name","push","reportReferences","words","kinds","includeSingleQuotedLiterals","word","references","includes","kind","isSingleQuotedLiteral","analyzeCommand","commandWords","filter","isRedirectionTarget","firstWord","undefined","shellWordIsStatic","value","headIndex","commandHeadIndex","head","commandName","shellCommandName","argumentWords","slice","program","shellProgramAfterC","reportBareArithmeticReferences","some","interpreterProgramWord","nestedShell","xargsShellProgram","token","source","current","index","redirectionTarget","wordCanStartComment","scanState","arithmeticContext","parameterBracketDepth","arithmeticBracketDepth","arithmeticShellSyntax","ensureWord","dynamic","flushWord","join","markDynamic","addReference","markArithmeticShellSyntax","advance","text","length","site","region","advanceEscape","nextCharacter","advanceExpansion","startsWith","firstName","readParameterName","readShellIdentifier","character","nextIndex","skipWhitespace","isArithmeticAssignment","referenceKind","chunk","scannerChunkAt","isShellWhitespace","startsShellRedirection","shellRedirectionLength","startsShellArithmetic","startsShellControl","shellControlLength","closingRunLength","repeat","isShellAssignment","split","at","test","skipDeclarationNames","expression","declarationExpression","identifier","arithmeticIdentifiers","assignmentIndex","indexOf","identifiers","jqOptionConsumesArguments","awkOptionConsumesArgument","sedOptionConsumesArgument","jqFlag","awkFlag","sedFlag","xargsOptionConsumesArgument","shell","shellName","start","prefix"],"mappings":"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"}
@@ -4,7 +4,11 @@ interface ArithSquareFrame {
4
4
  readonly kind: 'arith-square';
5
5
  readonly bracketDepth: number;
6
6
  }
7
- type ShellScanFrame = ShellFrame | ArithSquareFrame;
7
+ interface ArithFrame {
8
+ readonly kind: 'arith';
9
+ readonly parenthesisDepth: number;
10
+ }
11
+ type ShellScanFrame = Exclude<ShellFrame, 'arith'> | ArithFrame | ArithSquareFrame;
8
12
  export type ShellSiteContext = {
9
13
  readonly kind: 'unquoted' | 'single' | 'double';
10
14
  } | {
@@ -1 +1 @@
1
- {"version":3,"file":"shell-quoting.d.ts","sourceRoot":"","sources":["../../src/run/shell-quoting.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,eAAe,GACf,WAAW,GACX,OAAO,GACP,UAAU,GACV,aAAa,GACb,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAC;AACtD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AACD,KAAK,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GACxB;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAAC,GACjD;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CAAC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CAC7C;AAED,eAAO,MAAM,qBAAqB,EAAE,cAA6B,CAAC;AAIlE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,cAAc,CAgNpF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,gBAAgB,CAOzE"}
1
+ {"version":3,"file":"shell-quoting.d.ts","sourceRoot":"","sources":["../../src/run/shell-quoting.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,QAAQ,GACR,QAAQ,GACR,eAAe,GACf,eAAe,GACf,WAAW,GACX,OAAO,GACP,UAAU,GACV,aAAa,GACb,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAC;AACtD,UAAU,gBAAgB;IACxB,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AACD,UAAU,UAAU;IAClB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AACD,KAAK,cAAc,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAEnF,MAAM,MAAM,gBAAgB,GACxB;IAAC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;CAAC,GACjD;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAA;CAAC,CAAC;AAElE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,CAAC;IAC3C,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,wBAAwB,CAAC,EAAE,OAAO,CAAC;CAC7C;AAED,eAAO,MAAM,qBAAqB,EAAE,cAA6B,CAAC;AAIlE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,cAAc,CA4NpF;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,gBAAgB,CAOzE"}
@@ -107,13 +107,23 @@ export function scanShellLiteral(text, state) {
107
107
  advance(scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped), false);
108
108
  continue;
109
109
  }
110
- if (frame === 'arith') {
110
+ if (isArithFrame(frame)) {
111
111
  const arithEnd = matchShellLogicalPrefix(text, index, '))');
112
- if (arithEnd !== undefined) {
112
+ if (frame.parenthesisDepth === 0 && arithEnd !== undefined) {
113
113
  frames.pop();
114
114
  advance(arithEnd, false);
115
115
  continue;
116
116
  }
117
+ if (text[index] === ')') {
118
+ replaceTopArithFrame(frames, Math.max(0, frame.parenthesisDepth - 1));
119
+ advance(index + 1, false);
120
+ continue;
121
+ }
122
+ if (text[index] === '(') {
123
+ replaceTopArithFrame(frames, frame.parenthesisDepth + 1);
124
+ advance(index + 1, false);
125
+ continue;
126
+ }
117
127
  if (text[index] === '\\') {
118
128
  consumeShellEscape();
119
129
  continue;
@@ -207,7 +217,10 @@ function scanShellPlainStart(text, index, frames, previousCharacter, previousCha
207
217
  }
208
218
  const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');
209
219
  if (dollarArithStart !== undefined) {
210
- frames.push('arith');
220
+ frames.push({
221
+ kind: 'arith',
222
+ parenthesisDepth: 0
223
+ });
211
224
  return dollarArithStart;
212
225
  }
213
226
  const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');
@@ -240,7 +253,10 @@ function scanShellPlainStart(text, index, frames, previousCharacter, previousCha
240
253
  }
241
254
  const arithStart = matchShellLogicalPrefix(text, index, '((');
242
255
  if (arithStart !== undefined) {
243
- frames.push('arith');
256
+ frames.push({
257
+ kind: 'arith',
258
+ parenthesisDepth: 0
259
+ });
244
260
  return arithStart;
245
261
  }
246
262
  if (text[index] === "'") {
@@ -260,7 +276,10 @@ function scanShellPlainStart(text, index, frames, previousCharacter, previousCha
260
276
  function scanShellControlStart(text, index, frames) {
261
277
  const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');
262
278
  if (dollarArithStart !== undefined) {
263
- frames.push('arith');
279
+ frames.push({
280
+ kind: 'arith',
281
+ parenthesisDepth: 0
282
+ });
264
283
  return dollarArithStart;
265
284
  }
266
285
  const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');
@@ -329,7 +348,7 @@ function topFrame(frames) {
329
348
  return frames.at(-1);
330
349
  }
331
350
  function cloneShellScanFrame(frame) {
332
- if (isArithSquareFrame(frame)) return {
351
+ if (isArithSquareFrame(frame) || isArithFrame(frame)) return {
333
352
  ...frame
334
353
  };
335
354
  return frame;
@@ -339,6 +358,7 @@ function findUnsafeRegion(frames) {
339
358
  const frame = frames[index];
340
359
  if (frame === undefined) continue;
341
360
  if (isArithSquareFrame(frame)) return 'arith';
361
+ if (isArithFrame(frame)) return 'arith';
342
362
  if (frame !== 'single' && frame !== 'double') return frame;
343
363
  }
344
364
  return 'heredoc';
@@ -346,6 +366,17 @@ function findUnsafeRegion(frames) {
346
366
  function isArithSquareFrame(frame) {
347
367
  return typeof frame === 'object' && frame.kind === 'arith-square';
348
368
  }
369
+ function isArithFrame(frame) {
370
+ return typeof frame === 'object' && frame.kind === 'arith';
371
+ }
372
+ function replaceTopArithFrame(frames, parenthesisDepth) {
373
+ const topIndex = frames.length - 1;
374
+ const frame = frames[topIndex];
375
+ if (isArithFrame(frame)) frames[topIndex] = {
376
+ ...frame,
377
+ parenthesisDepth
378
+ };
379
+ }
349
380
  function replaceTopArithSquareFrame(frames, bracketDepth) {
350
381
  const topIndex = frames.length - 1;
351
382
  const frame = frames[topIndex];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/run/shell-quoting.ts"],"sourcesContent":["export type ShellFrame =\n | 'single'\n | 'double'\n | 'dollar-single'\n | 'dollar-double'\n | 'paren-sub'\n | 'arith'\n | 'backtick'\n | 'param-brace'\n | 'heredoc'\n | 'line-comment';\n\nexport type ShellUnsafeRegion = ShellFrame | 'escape';\ninterface ArithSquareFrame {\n readonly kind: 'arith-square';\n readonly bracketDepth: number;\n}\ntype ShellScanFrame = ShellFrame | ArithSquareFrame;\n\nexport type ShellSiteContext =\n | {readonly kind: 'unquoted' | 'single' | 'double'}\n | {readonly kind: 'unsafe'; readonly region: ShellUnsafeRegion};\n\nexport interface ShellScanState {\n readonly frames: readonly ShellScanFrame[];\n readonly pendingEscape?: boolean;\n readonly previousCharacter?: string;\n readonly previousCharacterEscaped?: boolean;\n}\n\nexport const initialShellScanState: ShellScanState = {frames: []};\n\nconst shellCommentStarterPrefixPattern = /\\s|[;&|()<>]/;\n\nexport function scanShellLiteral(text: string, state: ShellScanState): ShellScanState {\n const frames = state.frames.map(cloneShellScanFrame);\n let pendingEscape = state.pendingEscape ?? false;\n let previousCharacter = state.previousCharacter;\n let previousCharacterEscaped = state.previousCharacterEscaped ?? false;\n let index = 0;\n\n function advance(nextIndex: number, escaped: boolean): void {\n if (nextIndex > index) {\n previousCharacter = text[nextIndex - 1];\n previousCharacterEscaped = escaped;\n }\n index = nextIndex;\n }\n\n function consumeShellEscape(): void {\n const result = skipShellEscape(text, index);\n pendingEscape = result.pendingEscape;\n if (result.continuedLine) {\n index = result.index;\n return;\n }\n\n advance(result.index, result.consumedEscapedCharacter);\n }\n\n while (index < text.length) {\n if (pendingEscape) {\n pendingEscape = false;\n advance(index + 1, true);\n continue;\n }\n\n const frame = topFrame(frames);\n\n if (frame === 'single') {\n if (text[index] === \"'\") frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'dollar-single') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === \"'\") frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'backtick') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '`') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'double' || frame === 'dollar-double') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '\"') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'param-brace') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '}') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'paren-sub') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === ')') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (frame === 'arith') {\n const arithEnd = matchShellLogicalPrefix(text, index, '))');\n if (arithEnd !== undefined) {\n frames.pop();\n advance(arithEnd, false);\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (frame === 'heredoc') {\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'line-comment') {\n if (text[index] === '\\n') frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (isArithSquareFrame(frame)) {\n if (text[index] === '[') {\n replaceTopArithSquareFrame(frames, frame.bracketDepth + 1);\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === ']') {\n if (frame.bracketDepth === 0) {\n frames.pop();\n } else {\n replaceTopArithSquareFrame(frames, frame.bracketDepth - 1);\n }\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n }\n\n return {\n frames,\n ...(pendingEscape ? {pendingEscape} : {}),\n ...(previousCharacter === undefined ? {} : {previousCharacter}),\n ...(previousCharacterEscaped ? {previousCharacterEscaped} : {}),\n };\n}\n\nexport function classifyShellSite(state: ShellScanState): ShellSiteContext {\n if (state.pendingEscape === true) return {kind: 'unsafe', region: 'escape'};\n if (state.frames.length === 0) return {kind: 'unquoted'};\n if (state.frames.length === 1 && state.frames[0] === 'single') return {kind: 'single'};\n if (state.frames.length === 1 && state.frames[0] === 'double') return {kind: 'double'};\n\n return {kind: 'unsafe', region: findUnsafeRegion(state.frames)};\n}\n\nfunction scanShellPlainStart(\n text: string,\n index: number,\n frames: ShellScanFrame[],\n previousCharacter: string | undefined,\n previousCharacterEscaped: boolean,\n): number {\n if (startsShellLineComment(text, index, previousCharacter, previousCharacterEscaped)) {\n frames.push('line-comment');\n return index + 1;\n }\n\n const heredocStripTabsStart = matchShellLogicalPrefix(text, index, '<<-');\n if (heredocStripTabsStart !== undefined) {\n frames.push('heredoc');\n return heredocStripTabsStart;\n }\n\n const heredocStart = matchShellLogicalPrefix(text, index, '<<');\n if (heredocStart !== undefined) {\n frames.push('heredoc');\n return heredocStart;\n }\n\n const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');\n if (dollarArithStart !== undefined) {\n frames.push('arith');\n return dollarArithStart;\n }\n\n const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');\n if (arithSquareStart !== undefined) {\n frames.push({kind: 'arith-square', bracketDepth: 0});\n return arithSquareStart;\n }\n\n const parenSubStart = matchShellLogicalPrefix(text, index, '$(');\n if (parenSubStart !== undefined) {\n frames.push('paren-sub');\n return parenSubStart;\n }\n\n const paramBraceStart = matchShellLogicalPrefix(text, index, '${');\n if (paramBraceStart !== undefined) {\n frames.push('param-brace');\n return paramBraceStart;\n }\n\n const dollarSingleStart = matchShellLogicalPrefix(text, index, \"$'\");\n if (dollarSingleStart !== undefined) {\n frames.push('dollar-single');\n return dollarSingleStart;\n }\n\n const dollarDoubleStart = matchShellLogicalPrefix(text, index, '$\"');\n if (dollarDoubleStart !== undefined) {\n frames.push('dollar-double');\n return dollarDoubleStart;\n }\n\n const arithStart = matchShellLogicalPrefix(text, index, '((');\n if (arithStart !== undefined) {\n frames.push('arith');\n return arithStart;\n }\n\n if (text[index] === \"'\") {\n frames.push('single');\n return index + 1;\n }\n\n if (text[index] === '\"') {\n frames.push('double');\n return index + 1;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n return index + 1;\n }\n\n return index + 1;\n}\n\nfunction scanShellControlStart(text: string, index: number, frames: ShellScanFrame[]): number {\n const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');\n if (dollarArithStart !== undefined) {\n frames.push('arith');\n return dollarArithStart;\n }\n\n const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');\n if (arithSquareStart !== undefined) {\n frames.push({kind: 'arith-square', bracketDepth: 0});\n return arithSquareStart;\n }\n\n const parenSubStart = matchShellLogicalPrefix(text, index, '$(');\n if (parenSubStart !== undefined) {\n frames.push('paren-sub');\n return parenSubStart;\n }\n\n const paramBraceStart = matchShellLogicalPrefix(text, index, '${');\n if (paramBraceStart !== undefined) {\n frames.push('param-brace');\n return paramBraceStart;\n }\n\n const dollarSingleStart = matchShellLogicalPrefix(text, index, \"$'\");\n if (dollarSingleStart !== undefined) {\n frames.push('dollar-single');\n return dollarSingleStart;\n }\n\n const dollarDoubleStart = matchShellLogicalPrefix(text, index, '$\"');\n if (dollarDoubleStart !== undefined) {\n frames.push('dollar-double');\n return dollarDoubleStart;\n }\n\n return index + 1;\n}\n\nfunction matchShellLogicalPrefix(text: string, index: number, prefix: string): number | undefined {\n let nextIndex = index;\n\n for (let prefixIndex = 0; prefixIndex < prefix.length; prefixIndex += 1) {\n if (text[nextIndex] !== prefix[prefixIndex]) return undefined;\n nextIndex += 1;\n if (prefixIndex + 1 < prefix.length) nextIndex = skipShellLineContinuations(text, nextIndex);\n }\n\n return nextIndex;\n}\n\nfunction skipShellLineContinuations(text: string, index: number): number {\n let nextIndex = index;\n\n while (text[nextIndex] === '\\\\' && text[nextIndex + 1] === '\\n') {\n nextIndex += 2;\n }\n\n return nextIndex;\n}\n\nfunction skipShellEscape(\n text: string,\n index: number,\n): {\n readonly index: number;\n readonly pendingEscape: boolean;\n readonly consumedEscapedCharacter: boolean;\n readonly continuedLine: boolean;\n} {\n if (index + 1 >= text.length) {\n return {\n index: text.length,\n pendingEscape: true,\n consumedEscapedCharacter: false,\n continuedLine: false,\n };\n }\n\n return {\n index: index + 2,\n pendingEscape: false,\n consumedEscapedCharacter: true,\n continuedLine: text[index + 1] === '\\n',\n };\n}\n\nfunction topFrame(frames: readonly ShellScanFrame[]): ShellScanFrame | undefined {\n return frames.at(-1);\n}\n\nfunction cloneShellScanFrame(frame: ShellScanFrame): ShellScanFrame {\n if (isArithSquareFrame(frame)) return {...frame};\n return frame;\n}\n\nfunction findUnsafeRegion(frames: readonly ShellScanFrame[]): ShellFrame {\n for (let index = frames.length - 1; index >= 0; index -= 1) {\n const frame = frames[index];\n if (frame === undefined) continue;\n if (isArithSquareFrame(frame)) return 'arith';\n if (frame !== 'single' && frame !== 'double') return frame;\n }\n\n return 'heredoc';\n}\n\nfunction isArithSquareFrame(frame: ShellScanFrame | undefined): frame is ArithSquareFrame {\n return typeof frame === 'object' && frame.kind === 'arith-square';\n}\n\nfunction replaceTopArithSquareFrame(frames: ShellScanFrame[], bracketDepth: number): void {\n const topIndex = frames.length - 1;\n const frame = frames[topIndex];\n if (isArithSquareFrame(frame)) frames[topIndex] = {...frame, bracketDepth};\n}\n\nfunction startsShellLineComment(\n text: string,\n index: number,\n previousCharacter: string | undefined,\n previousCharacterEscaped: boolean,\n): boolean {\n if (text[index] !== '#') return false;\n if (previousCharacterEscaped) return false;\n if (previousCharacter === undefined) return true;\n\n return shellCommentStarterPrefixPattern.test(previousCharacter);\n}\n"],"names":["initialShellScanState","frames","shellCommentStarterPrefixPattern","scanShellLiteral","text","state","map","cloneShellScanFrame","pendingEscape","previousCharacter","previousCharacterEscaped","index","advance","nextIndex","escaped","consumeShellEscape","result","skipShellEscape","continuedLine","consumedEscapedCharacter","length","frame","topFrame","pop","scanShellControlStart","push","scanShellPlainStart","arithEnd","matchShellLogicalPrefix","undefined","isArithSquareFrame","replaceTopArithSquareFrame","bracketDepth","classifyShellSite","kind","region","findUnsafeRegion","startsShellLineComment","heredocStripTabsStart","heredocStart","dollarArithStart","arithSquareStart","parenSubStart","paramBraceStart","dollarSingleStart","dollarDoubleStart","arithStart","prefix","prefixIndex","skipShellLineContinuations","at","topIndex","test"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/run/shell-quoting.ts"],"sourcesContent":["export type ShellFrame =\n | 'single'\n | 'double'\n | 'dollar-single'\n | 'dollar-double'\n | 'paren-sub'\n | 'arith'\n | 'backtick'\n | 'param-brace'\n | 'heredoc'\n | 'line-comment';\n\nexport type ShellUnsafeRegion = ShellFrame | 'escape';\ninterface ArithSquareFrame {\n readonly kind: 'arith-square';\n readonly bracketDepth: number;\n}\ninterface ArithFrame {\n readonly kind: 'arith';\n readonly parenthesisDepth: number;\n}\ntype ShellScanFrame = Exclude<ShellFrame, 'arith'> | ArithFrame | ArithSquareFrame;\n\nexport type ShellSiteContext =\n | {readonly kind: 'unquoted' | 'single' | 'double'}\n | {readonly kind: 'unsafe'; readonly region: ShellUnsafeRegion};\n\nexport interface ShellScanState {\n readonly frames: readonly ShellScanFrame[];\n readonly pendingEscape?: boolean;\n readonly previousCharacter?: string;\n readonly previousCharacterEscaped?: boolean;\n}\n\nexport const initialShellScanState: ShellScanState = {frames: []};\n\nconst shellCommentStarterPrefixPattern = /\\s|[;&|()<>]/;\n\nexport function scanShellLiteral(text: string, state: ShellScanState): ShellScanState {\n const frames = state.frames.map(cloneShellScanFrame);\n let pendingEscape = state.pendingEscape ?? false;\n let previousCharacter = state.previousCharacter;\n let previousCharacterEscaped = state.previousCharacterEscaped ?? false;\n let index = 0;\n\n function advance(nextIndex: number, escaped: boolean): void {\n if (nextIndex > index) {\n previousCharacter = text[nextIndex - 1];\n previousCharacterEscaped = escaped;\n }\n index = nextIndex;\n }\n\n function consumeShellEscape(): void {\n const result = skipShellEscape(text, index);\n pendingEscape = result.pendingEscape;\n if (result.continuedLine) {\n index = result.index;\n return;\n }\n\n advance(result.index, result.consumedEscapedCharacter);\n }\n\n while (index < text.length) {\n if (pendingEscape) {\n pendingEscape = false;\n advance(index + 1, true);\n continue;\n }\n\n const frame = topFrame(frames);\n\n if (frame === 'single') {\n if (text[index] === \"'\") frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'dollar-single') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === \"'\") frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'backtick') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '`') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'double' || frame === 'dollar-double') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '\"') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'param-brace') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === '}') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n advance(index + 1, false);\n continue;\n }\n\n advance(scanShellControlStart(text, index, frames), false);\n continue;\n }\n\n if (frame === 'paren-sub') {\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n if (text[index] === ')') {\n frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (isArithFrame(frame)) {\n const arithEnd = matchShellLogicalPrefix(text, index, '))');\n if (frame.parenthesisDepth === 0 && arithEnd !== undefined) {\n frames.pop();\n advance(arithEnd, false);\n continue;\n }\n\n if (text[index] === ')') {\n replaceTopArithFrame(frames, Math.max(0, frame.parenthesisDepth - 1));\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '(') {\n replaceTopArithFrame(frames, frame.parenthesisDepth + 1);\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (frame === 'heredoc') {\n advance(index + 1, false);\n continue;\n }\n\n if (frame === 'line-comment') {\n if (text[index] === '\\n') frames.pop();\n advance(index + 1, false);\n continue;\n }\n\n if (isArithSquareFrame(frame)) {\n if (text[index] === '[') {\n replaceTopArithSquareFrame(frames, frame.bracketDepth + 1);\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === ']') {\n if (frame.bracketDepth === 0) {\n frames.pop();\n } else {\n replaceTopArithSquareFrame(frames, frame.bracketDepth - 1);\n }\n advance(index + 1, false);\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n continue;\n }\n\n if (text[index] === '\\\\') {\n consumeShellEscape();\n continue;\n }\n\n advance(\n scanShellPlainStart(text, index, frames, previousCharacter, previousCharacterEscaped),\n false,\n );\n }\n\n return {\n frames,\n ...(pendingEscape ? {pendingEscape} : {}),\n ...(previousCharacter === undefined ? {} : {previousCharacter}),\n ...(previousCharacterEscaped ? {previousCharacterEscaped} : {}),\n };\n}\n\nexport function classifyShellSite(state: ShellScanState): ShellSiteContext {\n if (state.pendingEscape === true) return {kind: 'unsafe', region: 'escape'};\n if (state.frames.length === 0) return {kind: 'unquoted'};\n if (state.frames.length === 1 && state.frames[0] === 'single') return {kind: 'single'};\n if (state.frames.length === 1 && state.frames[0] === 'double') return {kind: 'double'};\n\n return {kind: 'unsafe', region: findUnsafeRegion(state.frames)};\n}\n\nfunction scanShellPlainStart(\n text: string,\n index: number,\n frames: ShellScanFrame[],\n previousCharacter: string | undefined,\n previousCharacterEscaped: boolean,\n): number {\n if (startsShellLineComment(text, index, previousCharacter, previousCharacterEscaped)) {\n frames.push('line-comment');\n return index + 1;\n }\n\n const heredocStripTabsStart = matchShellLogicalPrefix(text, index, '<<-');\n if (heredocStripTabsStart !== undefined) {\n frames.push('heredoc');\n return heredocStripTabsStart;\n }\n\n const heredocStart = matchShellLogicalPrefix(text, index, '<<');\n if (heredocStart !== undefined) {\n frames.push('heredoc');\n return heredocStart;\n }\n\n const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');\n if (dollarArithStart !== undefined) {\n frames.push({kind: 'arith', parenthesisDepth: 0});\n return dollarArithStart;\n }\n\n const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');\n if (arithSquareStart !== undefined) {\n frames.push({kind: 'arith-square', bracketDepth: 0});\n return arithSquareStart;\n }\n\n const parenSubStart = matchShellLogicalPrefix(text, index, '$(');\n if (parenSubStart !== undefined) {\n frames.push('paren-sub');\n return parenSubStart;\n }\n\n const paramBraceStart = matchShellLogicalPrefix(text, index, '${');\n if (paramBraceStart !== undefined) {\n frames.push('param-brace');\n return paramBraceStart;\n }\n\n const dollarSingleStart = matchShellLogicalPrefix(text, index, \"$'\");\n if (dollarSingleStart !== undefined) {\n frames.push('dollar-single');\n return dollarSingleStart;\n }\n\n const dollarDoubleStart = matchShellLogicalPrefix(text, index, '$\"');\n if (dollarDoubleStart !== undefined) {\n frames.push('dollar-double');\n return dollarDoubleStart;\n }\n\n const arithStart = matchShellLogicalPrefix(text, index, '((');\n if (arithStart !== undefined) {\n frames.push({kind: 'arith', parenthesisDepth: 0});\n return arithStart;\n }\n\n if (text[index] === \"'\") {\n frames.push('single');\n return index + 1;\n }\n\n if (text[index] === '\"') {\n frames.push('double');\n return index + 1;\n }\n\n if (text[index] === '`') {\n frames.push('backtick');\n return index + 1;\n }\n\n return index + 1;\n}\n\nfunction scanShellControlStart(text: string, index: number, frames: ShellScanFrame[]): number {\n const dollarArithStart = matchShellLogicalPrefix(text, index, '$((');\n if (dollarArithStart !== undefined) {\n frames.push({kind: 'arith', parenthesisDepth: 0});\n return dollarArithStart;\n }\n\n const arithSquareStart = matchShellLogicalPrefix(text, index, '$[');\n if (arithSquareStart !== undefined) {\n frames.push({kind: 'arith-square', bracketDepth: 0});\n return arithSquareStart;\n }\n\n const parenSubStart = matchShellLogicalPrefix(text, index, '$(');\n if (parenSubStart !== undefined) {\n frames.push('paren-sub');\n return parenSubStart;\n }\n\n const paramBraceStart = matchShellLogicalPrefix(text, index, '${');\n if (paramBraceStart !== undefined) {\n frames.push('param-brace');\n return paramBraceStart;\n }\n\n const dollarSingleStart = matchShellLogicalPrefix(text, index, \"$'\");\n if (dollarSingleStart !== undefined) {\n frames.push('dollar-single');\n return dollarSingleStart;\n }\n\n const dollarDoubleStart = matchShellLogicalPrefix(text, index, '$\"');\n if (dollarDoubleStart !== undefined) {\n frames.push('dollar-double');\n return dollarDoubleStart;\n }\n\n return index + 1;\n}\n\nfunction matchShellLogicalPrefix(text: string, index: number, prefix: string): number | undefined {\n let nextIndex = index;\n\n for (let prefixIndex = 0; prefixIndex < prefix.length; prefixIndex += 1) {\n if (text[nextIndex] !== prefix[prefixIndex]) return undefined;\n nextIndex += 1;\n if (prefixIndex + 1 < prefix.length) nextIndex = skipShellLineContinuations(text, nextIndex);\n }\n\n return nextIndex;\n}\n\nfunction skipShellLineContinuations(text: string, index: number): number {\n let nextIndex = index;\n\n while (text[nextIndex] === '\\\\' && text[nextIndex + 1] === '\\n') {\n nextIndex += 2;\n }\n\n return nextIndex;\n}\n\nfunction skipShellEscape(\n text: string,\n index: number,\n): {\n readonly index: number;\n readonly pendingEscape: boolean;\n readonly consumedEscapedCharacter: boolean;\n readonly continuedLine: boolean;\n} {\n if (index + 1 >= text.length) {\n return {\n index: text.length,\n pendingEscape: true,\n consumedEscapedCharacter: false,\n continuedLine: false,\n };\n }\n\n return {\n index: index + 2,\n pendingEscape: false,\n consumedEscapedCharacter: true,\n continuedLine: text[index + 1] === '\\n',\n };\n}\n\nfunction topFrame(frames: readonly ShellScanFrame[]): ShellScanFrame | undefined {\n return frames.at(-1);\n}\n\nfunction cloneShellScanFrame(frame: ShellScanFrame): ShellScanFrame {\n if (isArithSquareFrame(frame) || isArithFrame(frame)) return {...frame};\n return frame;\n}\n\nfunction findUnsafeRegion(frames: readonly ShellScanFrame[]): ShellFrame {\n for (let index = frames.length - 1; index >= 0; index -= 1) {\n const frame = frames[index];\n if (frame === undefined) continue;\n if (isArithSquareFrame(frame)) return 'arith';\n if (isArithFrame(frame)) return 'arith';\n if (frame !== 'single' && frame !== 'double') return frame;\n }\n\n return 'heredoc';\n}\n\nfunction isArithSquareFrame(frame: ShellScanFrame | undefined): frame is ArithSquareFrame {\n return typeof frame === 'object' && frame.kind === 'arith-square';\n}\n\nfunction isArithFrame(frame: ShellScanFrame | undefined): frame is ArithFrame {\n return typeof frame === 'object' && frame.kind === 'arith';\n}\n\nfunction replaceTopArithFrame(frames: ShellScanFrame[], parenthesisDepth: number): void {\n const topIndex = frames.length - 1;\n const frame = frames[topIndex];\n if (isArithFrame(frame)) frames[topIndex] = {...frame, parenthesisDepth};\n}\n\nfunction replaceTopArithSquareFrame(frames: ShellScanFrame[], bracketDepth: number): void {\n const topIndex = frames.length - 1;\n const frame = frames[topIndex];\n if (isArithSquareFrame(frame)) frames[topIndex] = {...frame, bracketDepth};\n}\n\nfunction startsShellLineComment(\n text: string,\n index: number,\n previousCharacter: string | undefined,\n previousCharacterEscaped: boolean,\n): boolean {\n if (text[index] !== '#') return false;\n if (previousCharacterEscaped) return false;\n if (previousCharacter === undefined) return true;\n\n return shellCommentStarterPrefixPattern.test(previousCharacter);\n}\n"],"names":["initialShellScanState","frames","shellCommentStarterPrefixPattern","scanShellLiteral","text","state","map","cloneShellScanFrame","pendingEscape","previousCharacter","previousCharacterEscaped","index","advance","nextIndex","escaped","consumeShellEscape","result","skipShellEscape","continuedLine","consumedEscapedCharacter","length","frame","topFrame","pop","scanShellControlStart","push","scanShellPlainStart","isArithFrame","arithEnd","matchShellLogicalPrefix","parenthesisDepth","undefined","replaceTopArithFrame","Math","max","isArithSquareFrame","replaceTopArithSquareFrame","bracketDepth","classifyShellSite","kind","region","findUnsafeRegion","startsShellLineComment","heredocStripTabsStart","heredocStart","dollarArithStart","arithSquareStart","parenSubStart","paramBraceStart","dollarSingleStart","dollarDoubleStart","arithStart","prefix","prefixIndex","skipShellLineContinuations","at","topIndex","test"],"mappings":"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"}