MCPcopy
hub / github.com/codeaashu/claude-code / parsePowerShellCommandImpl

Function parsePowerShellCommandImpl

src/utils/powershell/parser.ts:1136–1261  ·  view source on GitHub ↗

* Parse a PowerShell command using the native AST parser. * Spawns pwsh to parse the command and returns structured results. * Results are memoized by command string. * * @param command - The PowerShell command to parse * @returns Parsed command structure, or a result with valid=false on failur

(
  command: string,
)

Source from the content-addressed store, hash-verified

1134 * @returns Parsed command structure, or a result with valid=false on failure
1135 */
1136async function parsePowerShellCommandImpl(
1137 command: string,
1138): Promise<ParsedPowerShellCommand> {
1139 // SECURITY: MAX_COMMAND_LENGTH is a UTF-8 BYTE budget (see derivation at the
1140 // constant definition). command.length counts UTF-16 code units; a CJK
1141 // character is 1 code unit but 3 UTF-8 bytes, so .length under-reports by
1142 // up to 3× and allows argv overflow on Windows → CreateProcess fails →
1143 // valid:false → deny rules degrade to ask. Finding #36.
1144 const commandBytes = Buffer.byteLength(command, 'utf8')
1145 if (commandBytes > MAX_COMMAND_LENGTH) {
1146 logForDebugging(
1147 `PowerShell parser: command too long (${commandBytes} bytes, max ${MAX_COMMAND_LENGTH})`,
1148 )
1149 return makeInvalidResult(
1150 command,
1151 `Command too long for parsing (${commandBytes} bytes). Maximum supported length is ${MAX_COMMAND_LENGTH} bytes.`,
1152 'CommandTooLong',
1153 )
1154 }
1155
1156 const pwshPath = await getCachedPowerShellPath()
1157 if (!pwshPath) {
1158 return makeInvalidResult(
1159 command,
1160 'PowerShell is not available',
1161 'NoPowerShell',
1162 )
1163 }
1164
1165 const script = buildParseScript(command)
1166
1167 // Pass the script to PowerShell via -EncodedCommand.
1168 // -EncodedCommand takes a Base64-encoded UTF-16LE string and executes it,
1169 // which avoids: (1) stdin interactive-mode issues where -File - produces
1170 // PS prompts and ANSI escapes in stdout, (2) command-line escaping issues,
1171 // (3) temp files. The script itself is large but well within OS arg limits
1172 // (Windows: 32K chars, Unix: typically 2MB+).
1173 const encodedScript = toUtf16LeBase64(script)
1174 const args = [
1175 '-NoProfile',
1176 '-NonInteractive',
1177 '-NoLogo',
1178 '-EncodedCommand',
1179 encodedScript,
1180 ]
1181
1182 // Spawn pwsh with one retry on timeout. On loaded CI runners (Windows
1183 // especially), pwsh spawn + .NET JIT + ParseInput occasionally exceeds 5s
1184 // even after CAN_SPAWN_PARSE_SCRIPT() warms the JIT. execa kills the process
1185 // but exitCode is undefined, which the old code reported as the misleading
1186 // "pwsh exited with code 1:" with empty stderr. A single retry absorbs
1187 // transient load spikes; a double timeout is reported as PwshTimeout.
1188 const parseTimeoutMs = getParseTimeoutMs()
1189 let stdout = ''
1190 let stderr = ''
1191 let code: number | null = null
1192 let timedOut = false
1193 for (let attempt = 0; attempt < 2; attempt++) {

Callers 1

parser.tsFile · 0.85

Calls 8

logForDebuggingFunction · 0.85
makeInvalidResultFunction · 0.85
getCachedPowerShellPathFunction · 0.85
buildParseScriptFunction · 0.85
toUtf16LeBase64Function · 0.85
getParseTimeoutMsFunction · 0.85
jsonParseFunction · 0.85
transformRawOutputFunction · 0.85

Tested by

no test coverage detected