From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2209) id 25ACC3858D1E; Tue, 19 Mar 2024 18:01:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 25ACC3858D1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1710871307; bh=/oWTf8JueAkgfRtr6KFMzM5bCLiuFQSgOua+nc1lWPM=; h=From:To:Subject:Date:From; b=kbIvNwH7lLzBeSdHI9l4KpUBFloDwXLLTyGWkszeqMwHVTGbveQdPSRDGrMYIvAOm B0QobA6viK0tZzKmm55bLhtDgzBILrRNAaUJ4d34zcAdBHXVoqiU2O8EuwBGtYZlYQ SOcjjx+Dh3IYnztpEv9Lcaa/oaZqlWBMqGSPuFgA= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: David Malcolm To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-9554] diagnostics: fix corrupt json/SARIF on stderr [PR114348] X-Act-Checkin: gcc X-Git-Author: David Malcolm X-Git-Refname: refs/heads/master X-Git-Oldrev: bc91e3870e9c984c180b478a3449a9a2e56cd107 X-Git-Newrev: 0bf99b1b7eda2f4c34b9f56b895980ea1c261765 Message-Id: <20240319180147.25ACC3858D1E@sourceware.org> Date: Tue, 19 Mar 2024 18:01:47 +0000 (GMT) List-Id: https://gcc.gnu.org/g:0bf99b1b7eda2f4c34b9f56b895980ea1c261765 commit r14-9554-g0bf99b1b7eda2f4c34b9f56b895980ea1c261765 Author: David Malcolm Date: Tue Mar 19 13:57:35 2024 -0400 diagnostics: fix corrupt json/SARIF on stderr [PR114348] Various values of -fdiagnostics-format= request machine-readable output on stderr, using JSON, but in various places we use fnotice to write free-form text to stderr, such as "compilation terminated", leading to corrupt JSON. Fix by having fnotice skip the output for such cases. gcc/ChangeLog: PR middle-end/114348 * diagnostic-format-json.cc (json_stderr_output_format::machine_readable_stderr_p): New. (json_file_output_format::machine_readable_stderr_p): New. * diagnostic-format-sarif.cc (sarif_stream_output_format::machine_readable_stderr_p): New. (sarif_file_output_format::machine_readable_stderr_p): New. * diagnostic.cc (diagnostic_context::action_after_output): Move "fnotice" to before "finish" call, so that we still have the diagnostic_context. (fnotice): Bail out if the user requested one of the machine-readable diagnostic output formats on stderr. * diagnostic.h (diagnostic_output_format::machine_readable_stderr_p): New pure virtual function. (diagnostic_text_output_format::machine_readable_stderr_p): New. (diagnostic_context::get_output_format): New accessor. Signed-off-by: David Malcolm Diff: --- gcc/diagnostic-format-json.cc | 8 ++++++++ gcc/diagnostic-format-sarif.cc | 8 ++++++++ gcc/diagnostic.cc | 12 +++++++++++- gcc/diagnostic.h | 10 ++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 51e016b6463..0782ae831eb 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -314,6 +314,10 @@ public: { flush_to_file (stderr); } + bool machine_readable_stderr_p () const final override + { + return true; + } }; class json_file_output_format : public json_output_format @@ -345,6 +349,10 @@ public: fclose (outf); free (filename); } + bool machine_readable_stderr_p () const final override + { + return false; + } private: char *m_base_file_name; diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc index 307b2f56c28..97c5943cd33 100644 --- a/gcc/diagnostic-format-sarif.cc +++ b/gcc/diagnostic-format-sarif.cc @@ -1750,6 +1750,10 @@ public: { m_builder.flush_to_file (m_stream); } + bool machine_readable_stderr_p () const final override + { + return m_stream == stderr; + } private: FILE *m_stream; }; @@ -1782,6 +1786,10 @@ public: fclose (outf); free (filename); } + bool machine_readable_stderr_p () const final override + { + return false; + } private: char *m_base_file_name; diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index 1d143fa7498..8e4621f8031 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -802,8 +802,8 @@ diagnostic_context::action_after_output (diagnostic_t diag_kind) case DK_FATAL: if (m_abort_on_error) real_abort (); - finish (); fnotice (stderr, "compilation terminated.\n"); + finish (); exit (FATAL_EXIT_CODE); default: @@ -2264,6 +2264,16 @@ diagnostic_context::emit_diagram (const diagnostic_diagram &diagram) void fnotice (FILE *file, const char *cmsgid, ...) { + /* If the user requested one of the machine-readable diagnostic output + formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then + emitting free-form text on stderr will lead to corrupt output. + Skip the message for such cases. */ + if (file == stderr && global_dc) + if (const diagnostic_output_format *output_format + = global_dc->get_output_format ()) + if (output_format->machine_readable_stderr_p ()) + return; + va_list ap; va_start (ap, cmsgid); diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 0a7c7e02b37..065ac784e25 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -210,6 +210,7 @@ public: virtual void on_end_diagnostic (const diagnostic_info &, diagnostic_t orig_diag_kind) = 0; virtual void on_diagram (const diagnostic_diagram &diagram) = 0; + virtual bool machine_readable_stderr_p () const = 0; protected: diagnostic_output_format (diagnostic_context &context) @@ -238,6 +239,10 @@ public: void on_end_diagnostic (const diagnostic_info &, diagnostic_t orig_diag_kind) override; void on_diagram (const diagnostic_diagram &diagram) override; + bool machine_readable_stderr_p () const final override + { + return false; + } }; /* A stack of sets of classifications: each entry in the stack is @@ -432,6 +437,11 @@ public: void emit_diagram (const diagnostic_diagram &diagram); + const diagnostic_output_format *get_output_format () const + { + return m_output_format; + } + /* Various setters for use by option-handling logic. */ void set_output_format (diagnostic_output_format *output_format); void set_text_art_charset (enum diagnostic_text_art_charset charset);