From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 79FB7385840D for ; Fri, 4 Nov 2022 16:42:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 79FB7385840D Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1667580152; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=LUpe6+H8BOz2kE9SuYQ7elzGF80X/MTwsot+dOq/5wQ=; b=iH2jA2WZ4T2tbIh+La5s0DmZLDhe9/QgsTVqBpX50Vhk4D5ZRMff6r36Cz9Bk9NwejH/BJ SCaKAQSJxJYNeuenlU9YIZu22dUjvQkJHGTea/0uiVV1yCtTBLnZWszQLGrXeo7wH0TQgZ lcnjFW1VXOSE63eJ46qrKHJN1pc0pjA= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-449-CKPT16STP5G6AO46BQK5zA-1; Fri, 04 Nov 2022 12:42:31 -0400 X-MC-Unique: CKPT16STP5G6AO46BQK5zA-1 Received: by mail-qt1-f197.google.com with SMTP id fb5-20020a05622a480500b003a525d52abcso4125631qtb.10 for ; Fri, 04 Nov 2022 09:42:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=mime-version:user-agent:content-transfer-encoding:references :in-reply-to:date:to:from:subject:message-id:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=LUpe6+H8BOz2kE9SuYQ7elzGF80X/MTwsot+dOq/5wQ=; b=UEGroE+8LGAMFPoeTWF2apTajaDQaf/VbwxXV35rGwfD/ZEM4OlPKZ6fNSYenXpaj/ WMXMdEBQhzVJQwXS0poWftR6+FiyIUrkIDcvIznX4A/vE3OKTh54RT22ix8qu+TcRqgp LmBDyk+mV1YHKO2wQpeahzT/A4+BMUgoUgZYpD6n6/AdWT2rGaiNGCPiqk4e91cOSs+X dpf/Ttv1ehY8TAGRrD13fT9M7RD+PGdWQEd001xc+Nb9Anv7l+jzkOb9HQNZWbtROTjU qCR0MGfBP5LcleHo162oJXYtrbUlttHDDgM7wY64wILqeVjJde7cBUrXT10qWUV4ttP0 8GAA== X-Gm-Message-State: ACrzQf2Pnx8ggm0HFaEko/nCSyeCec1tswGRBjWPiCy1TTMxoQsMgxAD BlfOnyyl8Bt9hoM/DJOFonQHZJ3+qN12G7Z+Swg8yD636EYMBaH3iqCqi/KHvpHA2XIorkhx1Q5 PlEK5fX66f6UVunE12A== X-Received: by 2002:ac8:7fc7:0:b0:3a5:71f2:c89a with SMTP id b7-20020ac87fc7000000b003a571f2c89amr1636985qtk.636.1667580150434; Fri, 04 Nov 2022 09:42:30 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6qcDTqd6fyURvLt2oliffzMX7mZNNU5o5mYxIVbpHVpLvkwPk4T27oi97zaszESCoTGESxvw== X-Received: by 2002:ac8:7fc7:0:b0:3a5:71f2:c89a with SMTP id b7-20020ac87fc7000000b003a571f2c89amr1636965qtk.636.1667580150081; Fri, 04 Nov 2022 09:42:30 -0700 (PDT) Received: from t14s.localdomain (c-73-69-212-193.hsd1.ma.comcast.net. [73.69.212.193]) by smtp.gmail.com with ESMTPSA id ff23-20020a05622a4d9700b00359961365f1sm2693821qtb.68.2022.11.04.09.42.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 04 Nov 2022 09:42:29 -0700 (PDT) Message-ID: Subject: Re: [PATCH 5/6] diagnostics: Support generated data in additional contexts From: David Malcolm To: Lewis Hyatt , gcc-patches@gcc.gnu.org Date: Fri, 04 Nov 2022 12:42:29 -0400 In-Reply-To: References: User-Agent: Evolution 3.44.4 (3.44.4-1.fc36) MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-10.8 required=5.0 tests=BAYES_00,BODY_8BITS,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Fri, 2022-11-04 at 09:44 -0400, Lewis Hyatt via Gcc-patches wrote: > Add awareness that diagnostic locations may be in generated buffers > rather > than an actual file to other places in the diagnostics code that may > care, > most notably SARIF output (which needs to obtain its own snapshots of > the code > involved). For edit context output, which outputs fixit hints as > diffs, for > now just make sure we ignore generated data buffers. At the moment, > there is > no ability for a fixit hint to be generated in such a buffer. >=20 > Because SARIF uses JSON as well, also add the ability to the > json::string > class to handle a buffer with nulls in the middle (since we place no > restriction on LC_GEN content) by providing the option to specify the > data > length. Please can you split this patch into three parts: - the SARIF part - the json changes - the edit-context.cc changes (I think this at least counts as an "obvious" change with respect to the other changes in the kit, though I'm still working my way through patch 4 in the kit). Please add a DejaGnu testcase to the SARIF part, with a diagnostic that references a generated data buffer; see gcc/testsuite/c-c++-common/diagnostic-format-sarif-file-*.c=20 for examples of SARIF testcases. Please add a selftest to the json change so that we have a unit test of constructing a json::string with an embedded NUL, and how we serialize such a string (probably to json.cc's test_writing_strings) Thanks Dave >=20 > gcc/ChangeLog: >=20 > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0* diagnostic-format-sarif= .cc (sarif_builder::xloc_to_fb): New > function. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(sarif_builder::maybe_mak= e_physical_location_object): Support > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0generated data locations. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(sarif_builder::make_arti= fact_location_object): Likewise. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(sarif_builder::maybe_mak= e_region_object_for_context): > Likewise. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(sarif_builder::make_arti= fact_object): Likewise. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(sarif_builder::maybe_mak= e_artifact_content_object): > Likewise. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(get_source_lines): Likew= ise. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0* edit-context.cc (edit_c= ontext::apply_fixit): Ignore > generated > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0locations if one should m= ake its way this far. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0* json.cc (string::string= ): Support non-null-terminated > string. > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0(string::print): Likewise= . > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0* json.h (class string): = Likewise. > --- > =C2=A0gcc/diagnostic-format-sarif.cc | 86 +++++++++++++++++++++----------= - > -- > =C2=A0gcc/edit-context.cc=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0 |=C2=A0 4 ++ > =C2=A0gcc/json.cc=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 17 +++++-- > =C2=A0gcc/json.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 5 += - > =C2=A04 files changed, 75 insertions(+), 37 deletions(-) >=20 > diff --git a/gcc/diagnostic-format-sarif.cc b/gcc/diagnostic-format- > sarif.cc > index 7110db4edd6..c2d18a1a16e 100644 > --- a/gcc/diagnostic-format-sarif.cc > +++ b/gcc/diagnostic-format-sarif.cc > @@ -125,7 +125,10 @@ private: > =C2=A0=C2=A0 json::array *maybe_make_kinds_array (diagnostic_event::meani= ng m) > const; > =C2=A0=C2=A0 json::object *maybe_make_physical_location_object (location_= t > loc); > =C2=A0=C2=A0 json::object *make_artifact_location_object (location_t loc)= ; > -=C2=A0 json::object *make_artifact_location_object (const char > *filename); > + > +=C2=A0 typedef std::pair filename_or_buffer; > +=C2=A0 json::object *make_artifact_location_object (filename_or_buffer > fb); > + > =C2=A0=C2=A0 json::object *make_artifact_location_object_for_pwd () const= ; > =C2=A0=C2=A0 json::object *maybe_make_region_object (location_t loc) cons= t; > =C2=A0=C2=A0 json::object *maybe_make_region_object_for_context (location= _t > loc) const; > @@ -146,16 +149,17 @@ private: > =C2=A0=C2=A0 json::object *make_reporting_descriptor_object_for_cwe_id (i= nt > cwe_id) const; > =C2=A0=C2=A0 json::object * > =C2=A0=C2=A0 make_reporting_descriptor_reference_object_for_cwe_id (int > cwe_id); > -=C2=A0 json::object *make_artifact_object (const char *filename); > -=C2=A0 json::object *maybe_make_artifact_content_object (const char > *filename) const; > -=C2=A0 json::object *maybe_make_artifact_content_object (const char > *filename, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 int start_line, > +=C2=A0 json::object *make_artifact_object (filename_or_buffer fb); > +=C2=A0 json::object * > +=C2=A0 maybe_make_artifact_content_object (filename_or_buffer fb) const; > +=C2=A0 json::object *maybe_make_artifact_content_object > (expanded_location xloc, > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0 int end_line) > const; > =C2=A0=C2=A0 json::object *make_fix_object (const rich_location &rich_loc= ); > =C2=A0=C2=A0 json::object *make_artifact_change_object (const rich_locati= on > &richloc); > =C2=A0=C2=A0 json::object *make_replacement_object (const fixit_hint &hin= t) > const; > =C2=A0=C2=A0 json::object *make_artifact_content_object (const char *text= ) > const; > =C2=A0=C2=A0 int get_sarif_column (expanded_location exploc) const; > +=C2=A0 static filename_or_buffer xloc_to_fb (expanded_location xloc); > =C2=A0 > =C2=A0=C2=A0 diagnostic_context *m_context; > =C2=A0 > @@ -166,7 +170,11 @@ private: > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 diagnostic group.=C2=A0 */ > =C2=A0=C2=A0 sarif_result *m_cur_group_result; > =C2=A0 > -=C2=A0 hash_set m_filenames; > +=C2=A0 /* If the second member is >0, then this is a buffer of generated > content, > +=C2=A0=C2=A0=C2=A0=C2=A0 with that length, not a filename.=C2=A0 */ > +=C2=A0 hash_set , > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int_hash > > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > m_filenam= es; > =C2=A0=C2=A0 bool m_seen_any_relative_paths; > =C2=A0=C2=A0 hash_set m_rule_id_set; > =C2=A0=C2=A0 json::array *m_rules_arr; > @@ -588,6 +596,15 @@ sarif_builder::make_location_object (const > diagnostic_event &event) > =C2=A0=C2=A0 return location_obj; > =C2=A0} > =C2=A0 > +/* Populate a filename_or_buffer pair from an expanded location.=C2=A0 *= / > +sarif_builder::filename_or_buffer > +sarif_builder::xloc_to_fb (expanded_location xloc) > +{ > +=C2=A0 if (xloc.generated_data_len) > +=C2=A0=C2=A0=C2=A0 return filename_or_buffer (xloc.generated_data, > xloc.generated_data_len); > +=C2=A0 return filename_or_buffer (xloc.file, 0); > +} > + > =C2=A0/* Make a physicalLocation object (SARIF v2.1.0 section 3.29) for > LOC, > =C2=A0=C2=A0=C2=A0 or return NULL; > =C2=A0=C2=A0=C2=A0 Add any filename to the m_artifacts.=C2=A0 */ > @@ -603,7 +620,7 @@ > sarif_builder::maybe_make_physical_location_object (location_t loc) > =C2=A0=C2=A0 /* "artifactLocation" property (SARIF v2.1.0 section 3.29.3)= .=C2=A0 */ > =C2=A0=C2=A0 json::object *artifact_loc_obj =3D make_artifact_location_ob= ject > (loc); > =C2=A0=C2=A0 phys_loc_obj->set ("artifactLocation", artifact_loc_obj); > -=C2=A0 m_filenames.add (LOCATION_FILE (loc)); > +=C2=A0 m_filenames.add (xloc_to_fb (expand_location (loc))); > =C2=A0 > =C2=A0=C2=A0 /* "region" property (SARIF v2.1.0 section 3.29.4).=C2=A0 */ > =C2=A0=C2=A0 if (json::object *region_obj =3D maybe_make_region_object (l= oc)) > @@ -627,7 +644,7 @@ > sarif_builder::maybe_make_physical_location_object (location_t loc) > =C2=A0json::object * > =C2=A0sarif_builder::make_artifact_location_object (location_t loc) > =C2=A0{ > -=C2=A0 return make_artifact_location_object (LOCATION_FILE (loc)); > +=C2=A0 return make_artifact_location_object (xloc_to_fb (expand_location > (loc))); > =C2=A0} > =C2=A0 > =C2=A0/* The ID value for use in "uriBaseId" properties (SARIF v2.1.0 > section 3.4.4) > @@ -639,10 +656,12 @@ sarif_builder::make_artifact_location_object > (location_t loc) > =C2=A0=C2=A0=C2=A0 or return NULL.=C2=A0 */ > =C2=A0 > =C2=A0json::object * > -sarif_builder::make_artifact_location_object (const char *filename) > +sarif_builder::make_artifact_location_object (filename_or_buffer fb) > =C2=A0{ > =C2=A0=C2=A0 json::object *artifact_loc_obj =3D new json::object (); > =C2=A0 > +=C2=A0 const auto filename =3D (fb.second ? special_fname_generated () : > fb.first); > + > =C2=A0=C2=A0 /* "uri" property (SARIF v2.1.0 section 3.4.3).=C2=A0 */ > =C2=A0=C2=A0 artifact_loc_obj->set ("uri", new json::string (filename)); > =C2=A0 > @@ -795,9 +814,7 @@ > sarif_builder::maybe_make_region_object_for_context (location_t loc) > const > =C2=A0 > =C2=A0=C2=A0 /* "snippet" property (SARIF v2.1.0 section 3.30.13).=C2=A0 = */ > =C2=A0=C2=A0 if (json::object *artifact_content_obj > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =3D maybe_make_artifact_conte= nt_object (exploc_start.file, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 exploc_start.line, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 exploc_finish.line)) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D maybe_make_artifact_conten= t_object (exploc_start, > exploc_finish.line)) > =C2=A0=C2=A0=C2=A0=C2=A0 region_obj->set ("snippet", artifact_content_obj= ); > =C2=A0 > =C2=A0=C2=A0 return region_obj; > @@ -1248,24 +1265,24 @@ sarif_builder::maybe_make_cwe_taxonomy_object > () const > =C2=A0/* Make an artifact object (SARIF v2.1.0 section 3.24).=C2=A0 */ > =C2=A0 > =C2=A0json::object * > -sarif_builder::make_artifact_object (const char *filename) > +sarif_builder::make_artifact_object (filename_or_buffer fb) > =C2=A0{ > =C2=A0=C2=A0 json::object *artifact_obj =3D new json::object (); > =C2=A0 > =C2=A0=C2=A0 /* "location" property (SARIF v2.1.0 section 3.24.2).=C2=A0 = */ > -=C2=A0 json::object *artifact_loc_obj =3D make_artifact_location_object > (filename); > +=C2=A0 json::object *artifact_loc_obj =3D make_artifact_location_object > (fb); > =C2=A0=C2=A0 artifact_obj->set ("location", artifact_loc_obj); > =C2=A0 > =C2=A0=C2=A0 /* "contents" property (SARIF v2.1.0 section 3.24.8).=C2=A0 = */ > =C2=A0=C2=A0 if (json::object *artifact_content_obj > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D maybe_make_artifact_conten= t_object (filename)) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D maybe_make_artifact_conten= t_object (fb)) > =C2=A0=C2=A0=C2=A0=C2=A0 artifact_obj->set ("contents", artifact_content_= obj); > =C2=A0 > =C2=A0=C2=A0 /* "sourceLanguage" property (SARIF v2.1.0 section 3.24.10).= =C2=A0 */ > =C2=A0=C2=A0 if (m_context->m_client_data_hooks) > =C2=A0=C2=A0=C2=A0=C2=A0 if (const char *source_lang > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=3D m_context->m_client_d= ata_hooks- > >maybe_get_sarif_source_language > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (filename)) > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (fb.first)) > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 artifact_obj->set ("sourceLanguage",= new json::string > (source_lang)); > =C2=A0 > =C2=A0=C2=A0 return artifact_obj; > @@ -1331,16 +1348,21 @@ maybe_read_file (const char *filename) > =C2=A0=C2=A0=C2=A0 full contents of FILENAME.=C2=A0 */ > =C2=A0 > =C2=A0json::object * > -sarif_builder::maybe_make_artifact_content_object (const char > *filename) const > +sarif_builder::maybe_make_artifact_content_object > (filename_or_buffer fb) const > =C2=A0{ > -=C2=A0 char *text_utf8 =3D maybe_read_file (filename); > -=C2=A0 if (!text_utf8) > -=C2=A0=C2=A0=C2=A0 return NULL; > - > -=C2=A0 json::object *artifact_content_obj =3D new json::object (); > -=C2=A0 artifact_content_obj->set ("text", new json::string (text_utf8)); > -=C2=A0 free (text_utf8); > - > +=C2=A0 json::object *artifact_content_obj =3D nullptr; > +=C2=A0 if (fb.second) > +=C2=A0=C2=A0=C2=A0 { > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 artifact_content_obj =3D new json::object= (); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 artifact_content_obj->set ("text", new js= on::string (fb.first, > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 > fb.second)); > +=C2=A0=C2=A0=C2=A0 } > +=C2=A0 else if (char *text_utf8 =3D maybe_read_file (fb.first)) > +=C2=A0=C2=A0=C2=A0 { > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 artifact_content_obj =3D new json::object= (); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 artifact_content_obj->set ("text", new js= on::string > (text_utf8)); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 free (text_utf8); > +=C2=A0=C2=A0=C2=A0 } > =C2=A0=C2=A0 return artifact_content_obj; > =C2=A0} > =C2=A0 > @@ -1348,15 +1370,14 @@ > sarif_builder::maybe_make_artifact_content_object (const char > *filename) const > =C2=A0=C2=A0=C2=A0 a freshly-allocated 0-terminated buffer containing the= m, or > NULL.=C2=A0 */ > =C2=A0 > =C2=A0static char * > -get_source_lines (const char *filename, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 int start_line, > +get_source_lines (expanded_location xloc, > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int end_line) > =C2=A0{ > =C2=A0=C2=A0 auto_vec result; > =C2=A0 > -=C2=A0 for (int line =3D start_line; line <=3D end_line; line++) > +=C2=A0 for (int line =3D xloc.line; line <=3D end_line; line++) > =C2=A0=C2=A0=C2=A0=C2=A0 { > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 char_span line_content =3D location_get_s= ource_line (filename, > line); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 char_span line_content =3D location_get_s= ource_line (xloc, > line); > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (!line_content.get_buffer ()) > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0return NULL; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 result.reserve (line_content.length = () + 1); > @@ -1370,14 +1391,13 @@ get_source_lines (const char *filename, > =C2=A0} > =C2=A0 > =C2=A0/* Make an artifactContent object (SARIF v2.1.0 section 3.3) for th= e > given > -=C2=A0=C2=A0 run of lines within FILENAME (including the endpoints).=C2= =A0 */ > +=C2=A0=C2=A0 run of lines starting at XLOC (including the endpoints).=C2= =A0 */ > =C2=A0 > =C2=A0json::object * > -sarif_builder::maybe_make_artifact_content_object (const char > *filename, > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 in= t start_line, > +sarif_builder::maybe_make_artifact_content_object (expanded_location > xloc, > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0 int end_line) > const > =C2=A0{ > -=C2=A0 char *text_utf8 =3D get_source_lines (filename, start_line, > end_line); > +=C2=A0 char *text_utf8 =3D get_source_lines (xloc, end_line); > =C2=A0 > =C2=A0=C2=A0 if (!text_utf8) > =C2=A0=C2=A0=C2=A0=C2=A0 return NULL; > diff --git a/gcc/edit-context.cc b/gcc/edit-context.cc > index 6879ddd41b4..aa95bc0834f 100644 > --- a/gcc/edit-context.cc > +++ b/gcc/edit-context.cc > @@ -301,8 +301,12 @@ edit_context::apply_fixit (const fixit_hint > *hint) > =C2=A0=C2=A0=C2=A0=C2=A0 return false; > =C2=A0=C2=A0 if (start.column =3D=3D 0) > =C2=A0=C2=A0=C2=A0=C2=A0 return false; > +=C2=A0 if (start.generated_data) > +=C2=A0=C2=A0=C2=A0 return false; > =C2=A0=C2=A0 if (next_loc.column =3D=3D 0) > =C2=A0=C2=A0=C2=A0=C2=A0 return false; > +=C2=A0 if (next_loc.generated_data) > +=C2=A0=C2=A0=C2=A0 return false; > =C2=A0 > =C2=A0=C2=A0 edited_file &file =3D get_or_insert_file (start.file); > =C2=A0=C2=A0 if (!m_valid) > diff --git a/gcc/json.cc b/gcc/json.cc > index 974f8c36825..3ebe8495e96 100644 > --- a/gcc/json.cc > +++ b/gcc/json.cc > @@ -190,6 +190,15 @@ string::string (const char *utf8) > =C2=A0{ > =C2=A0=C2=A0 gcc_assert (utf8); > =C2=A0=C2=A0 m_utf8 =3D xstrdup (utf8); > +=C2=A0 m_len =3D strlen (utf8); > +} > + > +string::string (const char *utf8, size_t len) > +{ > +=C2=A0 gcc_assert (utf8); > +=C2=A0 m_utf8 =3D XNEWVEC (char, len); > +=C2=A0 m_len =3D len; > +=C2=A0 memcpy (m_utf8, utf8, len); > =C2=A0} > =C2=A0 > =C2=A0/* Implementation of json::value::print for json::string.=C2=A0 */ > @@ -198,9 +207,9 @@ void > =C2=A0string::print (pretty_printer *pp) const > =C2=A0{ > =C2=A0=C2=A0 pp_character (pp, '"'); > -=C2=A0 for (const char *ptr =3D m_utf8; *ptr; ptr++) > +=C2=A0 for (size_t i =3D 0; i !=3D m_len; ++i) > =C2=A0=C2=A0=C2=A0=C2=A0 { > -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 char ch =3D *ptr; > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 char ch =3D m_utf8[i]; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 switch (ch) > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0{ > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case '"': > @@ -224,7 +233,9 @@ string::print (pretty_printer *pp) const > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case '\t': > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pp_string (pp, "\\= t"); > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 break; > - > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0case '\0': > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pp_string (pp, "\\0"); > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 break; > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0default: > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pp_character (pp, = ch); > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} > diff --git a/gcc/json.h b/gcc/json.h > index f272981259b..f7afd843dc5 100644 > --- a/gcc/json.h > +++ b/gcc/json.h > @@ -156,16 +156,19 @@ class integer_number : public value > =C2=A0class string : public value > =C2=A0{ > =C2=A0 public: > -=C2=A0 string (const char *utf8); > +=C2=A0 explicit string (const char *utf8); > +=C2=A0 string (const char *utf8, size_t len); > =C2=A0=C2=A0 ~string () { free (m_utf8); } > =C2=A0 > =C2=A0=C2=A0 enum kind get_kind () const final override { return JSON_STR= ING; } > =C2=A0=C2=A0 void print (pretty_printer *pp) const final override; > =C2=A0 > =C2=A0=C2=A0 const char *get_string () const { return m_utf8; } > +=C2=A0 size_t get_length () const { return m_len; } > =C2=A0 > =C2=A0 private: > =C2=A0=C2=A0 char *m_utf8; > +=C2=A0 size_t m_len; > =C2=A0}; > =C2=A0 > =C2=A0/* Subclass of value for the three JSON literals "true", "false", >=20