From f922fe3e038efd4232043147bfdb3bbf3cff2759 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Mon, 14 Oct 2024 15:39:39 +0200 Subject: [PATCH] gcc: use SARIF output with `--gcc-analyzer-bin` [EXPERIMENTAL] With https://copr.fedorainfracloud.org/coprs/dmalcolm/gcc-latest/ added to the `fedora-41-x86_64` mock config, this can be tested using the following commands: ``` koji download-build -a src units-2.23-3.fc41 csmock -f units-2.23-3.fc41.src.rpm -r fedora-41-x86_64 --install gcc-latest --gcc-analyzer-bin /opt/gcc-latest/bin/gcc ``` Depends-on: https://github.com/csutils/csdiff/pull/210 Related: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116613 Closes: https://github.com/csutils/csmock/pull/187 --- py/plugins/gcc.py | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/py/plugins/gcc.py b/py/plugins/gcc.py index 8d71810..0f08072 100644 --- a/py/plugins/gcc.py +++ b/py/plugins/gcc.py @@ -16,6 +16,7 @@ # along with csmock. If not, see . # standard imports +import os import subprocess # local imports @@ -25,10 +26,21 @@ CSGCCA_BIN = "/usr/bin/csgcca" +# directory for GCC results (currently used only with `--gcc-analyzer-bin`) +GCC_RESULTS_DIR = "/builddir/gcc-results" + CSMOCK_GCC_WRAPPER_NAME = 'csmock-gcc-wrapper' CSMOCK_GCC_WRAPPER_PATH = '/usr/bin/%s' % CSMOCK_GCC_WRAPPER_NAME -CSMOCK_GCC_WRAPPER_TEMPLATE = '#!/bin/bash\n' \ - 'exec %s "$@"' + +# script to run gcc analyzer and dump its output to a seaprate SARIF file in GCC_RESULTS_DIR +CSMOCK_GCC_WRAPPER_TEMPLATE = f"""#!/bin/bash +fn=$(flock {GCC_RESULTS_DIR} mktemp "{GCC_RESULTS_DIR}/$$-XXXX.sarif") +set -x +exec %s "$@" -fdiagnostics-format=json-file -fdiagnostics-add-output="sarif:file=$fn" +""" + +# command to read and join all captured SARIF files +FILTER_CMD = "csgrep --mode=json --remove-duplicates" SANITIZER_CAPTURE_DIR = "/builddir/gcc-sanitizer-capture" @@ -289,6 +301,24 @@ def csgcca_hook(results, mock): # tell csgcca to use the wrapped script rather than system gcc analyzer props.env["CSGCCA_ANALYZER_BIN"] = CSMOCK_GCC_WRAPPER_NAME + # create directory for gcc results + def create_gcc_results_dir_hook(results, mock): + cmd = f"mkdir -pv '{GCC_RESULTS_DIR}' && touch '{GCC_RESULTS_DIR}/empty.sarif'" + return mock.exec_mockbuild_cmd(cmd) + props.post_depinst_hooks += [create_gcc_results_dir_hook] + + # copy gcc results out of the chroot + props.copy_out_files += [GCC_RESULTS_DIR] + + # process all captured SARIF files + # TODO: avoid exceeding maximum command line length + def filter_hook(results): + src = os.path.join(results.dbgdir_raw, GCC_RESULTS_DIR[1:]) + dst = os.path.join(results.dbgdir_uni, "gcc-results.json") + cmd = f"cd {src} && {FILTER_CMD} *.sarif > {dst}" + return results.exec_cmd(cmd, shell=True) + props.post_process_hooks += [filter_hook] + # XXX: changing props this way is extremely fragile # insert csgcca right before cswrap to avoid chaining # csclng/cscppc while invoking `gcc -fanalyzer`