From 148066bd0560b5136692991dacba15c9f21caf96 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 24 Jul 2024 18:07:54 -0400 Subject: =?UTF-8?q?diagnostics:=20SARIF=20output:=20potentially=20add=20es?= =?UTF-8?q?caped=20renderings=20of=20source=20(=C2=A73.3.4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support to our SARIF output for cases where rich_loc.escape_on_output_p () is true, such as for -Wbidi-chars. In such cases, the pertinent SARIF "location" object gains a property bag with property "gcc/escapeNonAscii": true, and the "artifactContent" within the location's physical location's snippet" gains a "rendered" property (§3.3.4) that escapes non-ASCII text in the snippet, such as: "rendered": {"text": where "text" has a string value such as (for a "trojan source" attack): "9 | /* } if (isAdmin) begin admins only */\n" " | ~~~~~~~~ ~~~~~~~~ ^\n" " | | | |\n" " | | | end of bidirectional context\n" " | U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)\n" where the escaping is affected by -fdiagnostics-escape-format=; with -fdiagnostics-escape-format=bytes, the rendered text of the above is: "9 | /*<80> } <81>if (isAdmin)<81> <81> begin admins only */\n" " | ~~~~~~~~~~~~ ~~~~~~~~~~~~ ^\n" " | | | |\n" " | U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE) end of bidirectional context\n" The patch also refactors/adds enough selftest machinery to be able to test the snippet generation from within the selftest framework, rather than just within DejaGnu (where the regex-based testing isn't sophisticated enough to verify such properties as the above). gcc/ChangeLog: * Makefile.in (OBJS-libcommon): Add selftest-json.o. * diagnostic-format-sarif.cc: Include "selftest.h", "selftest-diagnostic.h", "selftest-diagnostic-show-locus.h", "selftest-json.h", and "text-range-label.h". (class content_renderer): New. (sarif_builder::m_rules_arr): Convert to std::unique_ptr. (sarif_builder::make_location_object): Add class escape_nonascii_renderer. If rich_loc.escape_on_output_p (), pass a nonnull escape_nonascii_renderer to maybe_make_physical_location_object as its snippet_renderer, and add a property bag property "gcc/escapeNonAscii" to the SARIF location object. For other overloads of make_location_object, pass nullptr for the snippet_renderer. (sarif_builder::maybe_make_region_object_for_context): Add "snippet_renderer" param and pass it to maybe_make_artifact_content_object. (sarif_builder::make_tool_object): Drop "const". (sarif_builder::make_driver_tool_component_object): Likewise. Use typesafe unique_ptr variant of object::set for setting "rules" property on driver_obj. (sarif_builder::maybe_make_artifact_content_object): Add param "r" and use it to potentially set the "rendered" property (§3.3.4). (selftest::test_make_location_object): New. (selftest::diagnostic_format_sarif_cc_tests): New. * diagnostic-show-locus.cc: Include "text-range-label.h" and "selftest-diagnostic-show-locus.h". (selftests::diagnostic_show_locus_fixture::diagnostic_show_locus_fixture): New. (selftests::test_layout_x_offset_display_utf8): Use diagnostic_show_locus_fixture to simplify and consolidate setup code. (selftests::test_diagnostic_show_locus_one_liner): Likewise. (selftests::test_one_liner_colorized_utf8): Likewise. (selftests::test_diagnostic_show_locus_one_liner_utf8): Likewise. * gcc-rich-location.h (class text_range_label): Move to new file text-range-label.h. * selftest-diagnostic-show-locus.h: New file, based on material in diagnostic-show-locus.cc. * selftest-json.cc: New file. * selftest-json.h: New file. * selftest-run-tests.cc (selftest::run_tests): Call selftest::diagnostic_format_sarif_cc_tests. * selftest.h (selftest::diagnostic_format_sarif_cc_tests): New decl. gcc/testsuite/ChangeLog: * c-c++-common/diagnostic-format-sarif-file-Wbidi-chars.c: Verify that we have a property bag with property "gcc/escapeNonAscii": true. Verify that we have a "rendered" property for a snippet. * gcc.dg/plugin/diagnostic_plugin_test_show_locus.c: Include "text-range-label.h". gcc/ChangeLog: * text-range-label.h: New file, taking class text_range_label from gcc-rich-location.h. libcpp/ChangeLog: * include/rich-location.h (semi_embedded_vec::semi_embedded_vec): Add copy ctor. (rich_location::rich_location): Remove "= delete" from decl of copy ctor. Add deleted decl of move ctor. (rich_location::operator=): Remove "= delete" from decl of copy assignment. Add deleted decl of move assignment. (fixit_hint::fixit_hint): Add copy ctor decl. Add deleted decl of move. (fixit_hint::operator=): Add copy assignment decl. Add deleted decl of move assignment. * line-map.cc (rich_location::rich_location): New copy ctor. (fixit_hint::fixit_hint): New copy ctor. Signed-off-by: David Malcolm --- libcpp/include/rich-location.h | 31 ++++++++++++++++++++++++++----- libcpp/line-map.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) (limited to 'libcpp') diff --git a/libcpp/include/rich-location.h b/libcpp/include/rich-location.h index ae4886f..11c181e 100644 --- a/libcpp/include/rich-location.h +++ b/libcpp/include/rich-location.h @@ -91,6 +91,7 @@ class semi_embedded_vec public: semi_embedded_vec (); ~semi_embedded_vec (); + semi_embedded_vec (const semi_embedded_vec &other); unsigned int count () const { return m_num; } T& operator[] (int idx); @@ -115,6 +116,21 @@ semi_embedded_vec::semi_embedded_vec () { } +/* Copy constructor for semi_embedded_vec. */ + +template +semi_embedded_vec::semi_embedded_vec (const semi_embedded_vec &other) +: m_num (0), + m_alloc (other.m_alloc), + m_extra (nullptr) +{ + if (other.m_extra) + m_extra = XNEWVEC (T, m_alloc); + + for (int i = 0; i < other.m_num; i++) + push (other[i]); +} + /* semi_embedded_vec's dtor. Release any dynamically-allocated memory. */ template @@ -387,11 +403,10 @@ class rich_location /* Destructor. */ ~rich_location (); - /* The class manages the memory pointed to by the elements of - the M_FIXIT_HINTS vector and is not meant to be copied or - assigned. */ - rich_location (const rich_location &) = delete; - void operator= (const rich_location &) = delete; + rich_location (const rich_location &); + rich_location (rich_location &&) = delete; + rich_location &operator= (const rich_location &) = delete; + rich_location &operator= (rich_location &&) = delete; /* Accessors. */ location_t get_loc () const { return get_loc (0); } @@ -547,6 +562,8 @@ protected: mutable expanded_location m_expanded_location; + /* The class manages the memory pointed to by the elements of + the m_fixit_hints vector. */ static const int MAX_STATIC_FIXIT_HINTS = 2; semi_embedded_vec m_fixit_hints; @@ -605,7 +622,11 @@ class fixit_hint fixit_hint (location_t start, location_t next_loc, const char *new_content); + fixit_hint (const fixit_hint &other); + fixit_hint (fixit_hint &&other) = delete; ~fixit_hint () { free (m_bytes); } + fixit_hint &operator= (const fixit_hint &) = delete; + fixit_hint &operator= (fixit_hint &&) = delete; bool affects_line_p (const line_maps *set, const char *file, diff --git a/libcpp/line-map.cc b/libcpp/line-map.cc index 41aee98..05c4daf 100644 --- a/libcpp/line-map.cc +++ b/libcpp/line-map.cc @@ -2175,6 +2175,26 @@ rich_location::rich_location (line_maps *set, location_t loc, add_range (loc, SHOW_RANGE_WITH_CARET, label, label_highlight_color); } +/* Copy ctor for rich_location. + Take a deep copy of the fixit hints, which are owneed; + everything else is borrowed. */ + +rich_location::rich_location (const rich_location &other) +: m_line_table (other.m_line_table), + m_ranges (other.m_ranges), + m_column_override (other.m_column_override), + m_have_expanded_location (other.m_have_expanded_location), + m_seen_impossible_fixit (other.m_seen_impossible_fixit), + m_fixits_cannot_be_auto_applied (other.m_fixits_cannot_be_auto_applied), + m_escape_on_output (other.m_escape_on_output), + m_expanded_location (other.m_expanded_location), + m_fixit_hints (), + m_path (other.m_path) +{ + for (unsigned i = 0; i < other.m_fixit_hints.count (); i++) + m_fixit_hints.push (new fixit_hint (*other.m_fixit_hints[i])); +} + /* The destructor for class rich_location. */ rich_location::~rich_location () @@ -2595,6 +2615,14 @@ fixit_hint::fixit_hint (location_t start, { } +fixit_hint::fixit_hint (const fixit_hint &other) +: m_start (other.m_start), + m_next_loc (other.m_next_loc), + m_bytes (xstrdup (other.m_bytes)), + m_len (other.m_len) +{ +} + /* Does this fix-it hint affect the given line? */ bool -- cgit v1.1