mirror of
https://github.com/rizsotto/scan-build.git
synced 2026-09-27 10:01:46 +02:00
run_command decoded subprocess output as strict UTF-8, so localized clang diagnostics or source lines echoed in another encoding raised UnicodeDecodeError and crashed the analysis worker. The decode in the CalledProcessError handler was worse: a decode failure there replaced the real error. Decode with errors="replace" in both places, like safe_readlines already does for report files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
# SPDX-License-Identifier: MIT
|
|
"""This module is a collection of methods commonly used in this project."""
|
|
|
|
import logging
|
|
import os
|
|
import os.path
|
|
import re
|
|
import shlex
|
|
import subprocess
|
|
|
|
|
|
def _unescape_shell_arg(arg: str) -> str:
|
|
"""Remove escaping characters from a shell argument.
|
|
|
|
Handles both quoted strings and escaped characters in shell arguments.
|
|
"""
|
|
if len(arg) >= 2 and arg[0] == arg[-1] and arg[0] == '"':
|
|
return re.sub(r'\\(["\\])', r"\1", arg[1:-1])
|
|
return re.sub(r"\\([\\ $%&\(\)\[\]\{\}\*|<>@?!])", r"\1", arg)
|
|
|
|
|
|
def shell_split(string: str) -> list[str]:
|
|
"""Split a command string into arguments and unescape them.
|
|
|
|
Args:
|
|
string: Command string to split
|
|
|
|
Returns:
|
|
List of unescaped command arguments
|
|
"""
|
|
return [_unescape_shell_arg(token) for token in shlex.split(string)]
|
|
|
|
|
|
def run_command(command: list[str], cwd: str | None = None) -> list[str]:
|
|
"""Run a command and return its output as lines.
|
|
|
|
Args:
|
|
command: Command as a list of arguments
|
|
cwd: Working directory for command execution (defaults to current directory)
|
|
|
|
Returns:
|
|
Command output split into lines
|
|
|
|
Raises:
|
|
subprocess.CalledProcessError: If command execution fails
|
|
"""
|
|
try:
|
|
directory = os.path.abspath(cwd) if cwd else os.getcwd()
|
|
logging.debug("exec command %s in %s", command, directory)
|
|
output: bytes = subprocess.check_output(
|
|
command,
|
|
cwd=directory,
|
|
stderr=subprocess.STDOUT,
|
|
)
|
|
# the output is not necessarily valid UTF-8 (localized diagnostics,
|
|
# source lines echoed in another encoding); never fail on decoding
|
|
return output.decode("utf-8", errors="replace").splitlines()
|
|
except subprocess.CalledProcessError as ex:
|
|
ex.output = ex.output.decode("utf-8", errors="replace").splitlines()
|
|
raise
|