Some SARIF files offload most of the properties within logical locations in the results to an array of "cached" instances in theRun.logicalLocations, so the information can be consolidated (and to support the "parentIndex" property, which is PR 116176).
Support such files in sarif-replay. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r15-7317-gcf24c0fa53870d. gcc/ChangeLog: * libsarifreplay.cc (sarif_replayer::handle_run_obj): Pass run to handle_result_obj. (sarif_replayer::handle_result_obj): Add run_obj param and pass it to handle_location_object and handle_thread_flow_object. (sarif_replayer::handle_thread_flow_object): Add run_obj param and pass it to handle_thread_flow_location_object. (sarif_replayer::handle_thread_flow_location_object): Add run_obj param and pass it to handle_location_object. (sarif_replayer::handle_location_object): Add run_obj param and pass it to handle_logical_location_object. (sarif_replayer::handle_logical_location_object): Add run_obj param. If the run_obj is non-null and has "logicalLocations", then use these "cached" logical locations if we see an "index" property, as per §3.33.3 gcc/testsuite/ChangeLog: * sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif: New test. * sarif-replay.dg/2.1.0-valid/spec-example-4.sarif: Update expected output to reflect that we now find the function name for the events in the path. Signed-off-by: David Malcolm <dmalc...@redhat.com> --- gcc/libsarifreplay.cc | 70 +++++++++++++++++-- .../3.33.3-index-out-of-range.sarif | 32 +++++++++ .../2.1.0-valid/spec-example-4.sarif | 2 +- 3 files changed, 96 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif diff --git a/gcc/libsarifreplay.cc b/gcc/libsarifreplay.cc index eb829064194d..61d9565588ed 100644 --- a/gcc/libsarifreplay.cc +++ b/gcc/libsarifreplay.cc @@ -277,6 +277,7 @@ private: // "result" object (§3.27) enum status handle_result_obj (const json::object &result_obj, + const json::object &run_obj, const json::object &tool_obj); json::result<enum diagnostic_level, enum status> get_level_from_level_str (const json::string &level_str); @@ -284,6 +285,7 @@ private: // "location" object (§3.28) enum status handle_location_object (const json::object &location_obj, + const json::object &run_obj, libgdiagnostics::physical_location &out_physical_loc, libgdiagnostics::logical_location &out_logical_loc); @@ -301,16 +303,19 @@ private: // "logicalLocation" object (§3.33) enum status handle_logical_location_object (const json::object &logical_loc_obj, + const json::object *run_obj, libgdiagnostics::logical_location &out); // "threadFlow" object (§3.37) enum status handle_thread_flow_object (const json::object &thread_flow_obj, + const json::object &run_obj, libgdiagnostics::execution_path &out); // "threadFlowLocation" object (§3.38) enum status handle_thread_flow_location_object (const json::object &tflow_loc_obj, + const json::object &run_obj, libgdiagnostics::execution_path &out); // reportingDescriptor lookup (§3.52.3) @@ -806,7 +811,9 @@ sarif_replayer::handle_run_obj (const json::object &run_obj) = require_object_for_element (*element, prop_results); if (!result_obj) return status::err_invalid_sarif; - enum status s = handle_result_obj (*result_obj, *tool_obj); + enum status s = handle_result_obj (*result_obj, + run_obj, + *tool_obj); if (s != status::ok) return s; } @@ -974,6 +981,7 @@ sarif_replayer::get_level_from_level_str (const json::string &level_str) enum status sarif_replayer::handle_result_obj (const json::object &result_obj, + const json::object &run_obj, const json::object &tool_obj) { const json::object *rule_obj = nullptr; @@ -1025,7 +1033,7 @@ sarif_replayer::handle_result_obj (const json::object &result_obj, = require_object_for_element (*locations_arr->get (0), locations_prop); if (!location_obj) return status::err_invalid_sarif; - enum status s = handle_location_object (*location_obj, + enum status s = handle_location_object (*location_obj, run_obj, physical_loc, logical_loc); if (s != status::ok) @@ -1059,7 +1067,7 @@ sarif_replayer::handle_result_obj (const json::object &result_obj, prop_thread_flows); if (!thread_flow_obj) return status::err_invalid_sarif; - handle_thread_flow_object (*thread_flow_obj, path); + handle_thread_flow_object (*thread_flow_obj, run_obj, path); } } } @@ -1104,7 +1112,7 @@ sarif_replayer::handle_result_obj (const json::object &result_obj, prop_related_locations); if (!location_obj) return status::err_invalid_sarif; - enum status s = handle_location_object (*location_obj, + enum status s = handle_location_object (*location_obj, run_obj, physical_loc, logical_loc); if (s != status::ok) @@ -1438,6 +1446,7 @@ lookup_plain_text_within_result_message (const json::object *tool_component_obj, enum status sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj, + const json::object &run_obj, libgdiagnostics::execution_path &out) { const property_spec_ref locations ("threadFlow", "locations", "3.37.6"); @@ -1454,7 +1463,7 @@ sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj, = require_object_for_element (*location, locations); if (!tflow_loc_obj) return status::err_invalid_sarif; - handle_thread_flow_location_object (*tflow_loc_obj, out); + handle_thread_flow_location_object (*tflow_loc_obj, run_obj, out); } return status::ok; @@ -1466,6 +1475,7 @@ sarif_replayer::handle_thread_flow_object (const json::object &thread_flow_obj, enum status sarif_replayer:: handle_thread_flow_location_object (const json::object &tflow_loc_obj, + const json::object &run_obj, libgdiagnostics::execution_path &path) { libgdiagnostics::physical_location physical_loc; @@ -1479,8 +1489,8 @@ handle_thread_flow_location_object (const json::object &tflow_loc_obj, location_prop)) { /* location object (§3.28). */ - enum status s - = handle_location_object (*location_obj, physical_loc, logical_loc); + enum status s = handle_location_object (*location_obj, run_obj, + physical_loc, logical_loc); if (s != status::ok) return s; @@ -1552,6 +1562,7 @@ handle_thread_flow_location_object (const json::object &tflow_loc_obj, enum status sarif_replayer:: handle_location_object (const json::object &location_obj, + const json::object &run_obj, libgdiagnostics::physical_location &out_physical_loc, libgdiagnostics::logical_location &out_logical_loc) { @@ -1586,6 +1597,7 @@ handle_location_object (const json::object &location_obj, if (!logical_loc_obj) return status::err_invalid_sarif; enum status s = handle_logical_location_object (*logical_loc_obj, + &run_obj, out_logical_loc); if (s != status::ok) return s; @@ -1743,6 +1755,10 @@ handle_region_object (const json::object ®ion_obj, } /* Handle a "logicalLocation" object (§3.33), using it to populate OUT. + + If RUN_OBJ is non-null, and has "logicalLocations", then use it if we + see an "index" property. + Known limitations: - doesn't yet handle "parentIndex" property (§3.33.8) */ @@ -1750,8 +1766,48 @@ handle_region_object (const json::object ®ion_obj, enum status sarif_replayer:: handle_logical_location_object (const json::object &logical_loc_obj, + const json::object *run_obj, libgdiagnostics::logical_location &out) { + if (run_obj) + { + const property_spec_ref name_prop ("logicalLocation", "index", "3.33.3"); + if (auto index_js_int + = get_optional_property<json::integer_number> (logical_loc_obj, + name_prop)) + { + const long index = index_js_int->get (); + /* If "index" is present, then there must be theRun.logicalLocations + and it must have a cached object at that index. */ + const property_spec_ref run_logical_locs_prop + ("run", "logicalLocations", "3.14.17"); + if (auto logical_locs_arr + = get_required_property<json::array> (*run_obj, + run_logical_locs_prop)) + { + /* "index" must be in range */ + if (index < 0 || index >= (long)logical_locs_arr->length ()) + return report_invalid_sarif (*index_js_int, name_prop, + "index value %li is out of range" + " for theRun.logicalLocations", + index); + + json::value *element = logical_locs_arr->get (index); + + if (const json::object *obj + = require_object (*element,run_logical_locs_prop)) + { + /* Use this "cached" object instead. + Pass nullptr for the run object so that we + don't recurse. */ + return handle_logical_location_object (*obj, nullptr, out); + } + } + } + } + + // Otherwise use the properties from LOGICAL_LOC_OBJ. + const property_spec_ref name_prop ("logicalLocation", "name", "3.33.4"); const char *short_name = nullptr; if (auto name_jstr = get_optional_property<json::string> (logical_loc_obj, diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif new file mode 100644 index 000000000000..ef22614776c5 --- /dev/null +++ b/gcc/testsuite/sarif-replay.dg/2.1.0-invalid/3.33.3-index-out-of-range.sarif @@ -0,0 +1,32 @@ +{ + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "placeholder" + } + }, + "results": [ + { + "message": {"text": "placeholder"}, + "locations": [ + { + "logicalLocations": [ + { + "index": 42 // { dg-error "index value 42 is out of range for theRun.logicalLocations \\\[SARIF v2.1.0 §3.33.3\\\]" } + } + ] + } + ] + } + ], + "logicalLocations": [] + } + ] +} + +/* { dg-begin-multiline-output "" } + 17 | "index": 42 + | ^~ + { dg-end-multiline-output "" } */ diff --git a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif index 27a0767bd0ef..c0f0fd50e0e9 100644 --- a/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif +++ b/gcc/testsuite/sarif-replay.dg/2.1.0-valid/spec-example-4.sarif @@ -749,7 +749,7 @@ /* { dg-begin-multiline-output "" } In function 'collections::list::add': collections/list.h:15:9: error: Variable "ptr" was used without being initialized. It was declared here. [C2001] - events 1-3 + 'add': events 1-3 ...... { dg-end-multiline-output "" } */ /* { dg-begin-multiline-output "" } -- 2.26.3