aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2025-01-28 10:36:53 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2025-01-28 10:36:53 -0500
commitb4bd06774ced72d5f0059ec55022840ad3f37fa4 (patch)
tree48f3bce7badcfc97a1baa6280d43e97df162eeb8
parent98b2009b8768f8790dff9edbe00742bcdf2b7482 (diff)
downloadgcc-b4bd06774ced72d5f0059ec55022840ad3f37fa4.zip
gcc-b4bd06774ced72d5f0059ec55022840ad3f37fa4.tar.gz
gcc-b4bd06774ced72d5f0059ec55022840ad3f37fa4.tar.bz2
sarif output: escape braces in messages [PR118675]
gcc/ChangeLog: PR other/118675 * diagnostic-format-sarif.cc: Define INCLUDE_STRING. (escape_braces): New. (set_string_property_escaping_braces): New. (sarif_builder::make_message_object): Escape braces in the "text" property. (sarif_builder::make_message_object_for_diagram): Likewise, and for the "markdown" property. (sarif_builder::make_multiformat_message_string): Likewise for the "text" property. (xelftest::test_message_with_braces): New. (selftest::diagnostic_format_sarif_cc_tests): Call it. gcc/testsuite/ChangeLog: PR other/118675 * gcc.dg/sarif-output/bad-binary-op.py: Update expected output for escaping of braces in message text. * gcc.dg/sarif-output/missing-semicolon.py: Likewise. * gcc.dg/sarif-output/multiple-outputs.py: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
-rw-r--r--gcc/diagnostic-format-sarif.cc68
-rw-r--r--gcc/testsuite/gcc.dg/sarif-output/bad-binary-op.py6
-rw-r--r--gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py2
-rw-r--r--gcc/testsuite/gcc.dg/sarif-output/multiple-outputs.py2
4 files changed, 69 insertions, 9 deletions
diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format-sarif.cc
index 168a52f..554992b 100644
--- a/gcc/diagnostic-format-sarif.cc
+++ b/gcc/diagnostic-format-sarif.cc
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#define INCLUDE_LIST
#define INCLUDE_MAP
+#define INCLUDE_STRING
#define INCLUDE_VECTOR
#include "system.h"
#include "coretypes.h"
@@ -2821,6 +2822,38 @@ sarif_builder::maybe_make_kinds_array (diagnostic_event::meaning m) const
return kinds_arr;
}
+/* In "3.11.5 Messages with placeholders":
+ "Within both plain text and formatted message strings, the characters
+ "{" and "}" SHALL be represented by the character sequences
+ "{{" and "}}" respectively." */
+
+static std::string
+escape_braces (const char *text)
+{
+ std::string result;
+ while (char ch = *text++)
+ switch (ch)
+ {
+ case '{':
+ case '}':
+ result += ch;
+ /* Fall through. */
+ default:
+ result += ch;
+ break;
+ }
+ return result;
+}
+
+static void
+set_string_property_escaping_braces (json::object &obj,
+ const char *property_name,
+ const char *value)
+{
+ std::string escaped (escape_braces (value));
+ obj.set_string (property_name, escaped.c_str ());
+}
+
/* Make a "message" object (SARIF v2.1.0 section 3.11) for MSG. */
std::unique_ptr<sarif_message>
@@ -2829,7 +2862,8 @@ sarif_builder::make_message_object (const char *msg) const
auto message_obj = ::make_unique<sarif_message> ();
/* "text" property (SARIF v2.1.0 section 3.11.8). */
- message_obj->set_string ("text", msg);
+ set_string_property_escaping_braces (*message_obj,
+ "text", msg);
return message_obj;
}
@@ -2844,7 +2878,8 @@ sarif_builder::make_message_object_for_diagram (const diagnostic_diagram &diagra
auto message_obj = ::make_unique<sarif_message> ();
/* "text" property (SARIF v2.1.0 section 3.11.8). */
- message_obj->set_string ("text", diagram.get_alt_text ());
+ set_string_property_escaping_braces (*message_obj,
+ "text", diagram.get_alt_text ());
pretty_printer *const pp = m_printer;
char *saved_prefix = pp_take_prefix (pp);
@@ -2857,7 +2892,8 @@ sarif_builder::make_message_object_for_diagram (const diagnostic_diagram &diagra
pp_set_prefix (pp, saved_prefix);
/* "markdown" property (SARIF v2.1.0 section 3.11.9). */
- message_obj->set_string ("markdown", pp_formatted_text (pp));
+ set_string_property_escaping_braces (*message_obj,
+ "markdown", pp_formatted_text (pp));
pp_clear_output_area (pp);
@@ -2873,7 +2909,8 @@ sarif_builder::make_multiformat_message_string (const char *msg) const
auto message_obj = ::make_unique<sarif_multiformat_message_string> ();
/* "text" property (SARIF v2.1.0 section 3.12.3). */
- message_obj->set_string ("text", msg);
+ set_string_property_escaping_braces (*message_obj,
+ "text", msg);
return message_obj;
}
@@ -4341,6 +4378,28 @@ test_message_with_embedded_link (enum sarif_version version)
}
}
+/* Verify that braces in messages get escaped, as per
+ 3.11.5 ("Messages with placeholders"). */
+
+static void
+test_message_with_braces (enum sarif_version version)
+{
+ auto_fix_quotes fix_quotes;
+ {
+ test_sarif_diagnostic_context dc ("test.c", version);
+ rich_location richloc (line_table, UNKNOWN_LOCATION);
+ dc.report (DK_ERROR, richloc, nullptr, 0,
+ "open brace: %qs close brace: %qs",
+ "{", "}");
+ std::unique_ptr<sarif_log> log = dc.flush_to_object ();
+
+ auto message_obj = get_message_from_log (log.get ());
+ ASSERT_JSON_STRING_PROPERTY_EQ
+ (message_obj, "text",
+ "open brace: `{{' close brace: `}}'");
+ }
+}
+
static void
test_buffering (enum sarif_version version)
{
@@ -4457,6 +4516,7 @@ diagnostic_format_sarif_cc_tests ()
test_simple_log (version);
test_message_with_embedded_link (version);
+ test_message_with_braces (version);
test_buffering (version);
}
diff --git a/gcc/testsuite/gcc.dg/sarif-output/bad-binary-op.py b/gcc/testsuite/gcc.dg/sarif-output/bad-binary-op.py
index fe139e6..2281c06 100644
--- a/gcc/testsuite/gcc.dg/sarif-output/bad-binary-op.py
+++ b/gcc/testsuite/gcc.dg/sarif-output/bad-binary-op.py
@@ -45,7 +45,7 @@ def test_error_location(sarif):
assert result['level'] == 'error'
assert result['message']['text'] \
- == "invalid operands to binary + (have 'S' {aka 'struct s'} and 'T' {aka 'struct t'})"
+ == "invalid operands to binary + (have 'S' {{aka 'struct s'}} and 'T' {{aka 'struct t'}})"
locations = result['locations']
assert len(locations) == 1
@@ -63,8 +63,8 @@ def test_error_location(sarif):
assert annotations[0]['startLine'] == EXPECTED_LINE
assert annotations[0]['startColumn'] == 10
assert annotations[0]['endColumn'] == 22
- assert annotations[0]['message']['text'] == "S {aka struct s}"
+ assert annotations[0]['message']['text'] == "S {{aka struct s}}"
assert annotations[1]['startLine'] == EXPECTED_LINE
assert annotations[1]['startColumn'] == 25
assert annotations[1]['endColumn'] == 37
- assert annotations[1]['message']['text'] == "T {aka struct t}"
+ assert annotations[1]['message']['text'] == "T {{aka struct t}}"
diff --git a/gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py b/gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py
index 58c0a7d..a0f8483 100644
--- a/gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py
+++ b/gcc/testsuite/gcc.dg/sarif-output/missing-semicolon.py
@@ -43,7 +43,7 @@ def test_location_relationships(sarif):
result = results[0]
assert result['level'] == 'error'
- assert result['message']['text'] == "expected ';' before '}' token"
+ assert result['message']['text'] == "expected ';' before '}}' token"
locations = result['locations']
assert len(locations) == 1
diff --git a/gcc/testsuite/gcc.dg/sarif-output/multiple-outputs.py b/gcc/testsuite/gcc.dg/sarif-output/multiple-outputs.py
index 8febfac..4de91c2 100644
--- a/gcc/testsuite/gcc.dg/sarif-output/multiple-outputs.py
+++ b/gcc/testsuite/gcc.dg/sarif-output/multiple-outputs.py
@@ -36,7 +36,7 @@ def test_result(sarif):
result = results[0]
assert result['level'] == 'error'
- assert result['message']['text'] == "expected ';' before '}' token"
+ assert result['message']['text'] == "expected ';' before '}}' token"
locations = result['locations']
assert len(locations) == 1