case LOGICAL_LOCATION_KIND_UNKNOWN:
return nullptr;
+ /* Kinds within executable code. */
case LOGICAL_LOCATION_KIND_FUNCTION:
return "function";
case LOGICAL_LOCATION_KIND_MEMBER:
return "parameter";
case LOGICAL_LOCATION_KIND_VARIABLE:
return "variable";
+
+ /* Kinds within XML or HTML documents. */
+ case LOGICAL_LOCATION_KIND_ELEMENT:
+ return "element";
+ case LOGICAL_LOCATION_KIND_ATTRIBUTE:
+ return "attribute";
+ case LOGICAL_LOCATION_KIND_TEXT:
+ return "text";
+ case LOGICAL_LOCATION_KIND_COMMENT:
+ return "comment";
+ case LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION:
+ return "processingInstruction";
+ case LOGICAL_LOCATION_KIND_DTD:
+ return "dtd";
+ case LOGICAL_LOCATION_KIND_DECLARATION:
+ return "declaration";
+
+ /* Kinds within JSON documents. */
+ case LOGICAL_LOCATION_KIND_OBJECT:
+ return "object";
+ case LOGICAL_LOCATION_KIND_ARRAY:
+ return "array";
+ case LOGICAL_LOCATION_KIND_PROPERTY:
+ return "property";
+ case LOGICAL_LOCATION_KIND_VALUE:
+ return "value";
}
}
This roughly corresponds to the ``kind`` property in SARIF v2.1.0
(`ยง3.33.7 <https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/sarif-v2.1.0-errata01-os-complete.html#_Toc141790976>`_).
+ Kinds within executable code:
+
.. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION
.. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER
.. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE
+ Kinds within XML or HTML documents:
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION
+
+ Kinds within JSON documents:
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY
+
+ .. macro:: DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE
+
``parent`` can be NULL; if non-NULL it can be used to express tree-like
nesting of logical locations, such as in::
{
default:
gcc_unreachable ();
+
case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
return LOGICAL_LOCATION_KIND_FUNCTION;
case DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER:
return LOGICAL_LOCATION_KIND_PARAMETER;
case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
return LOGICAL_LOCATION_KIND_VARIABLE;
+
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT:
+ return LOGICAL_LOCATION_KIND_ELEMENT;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE:
+ return LOGICAL_LOCATION_KIND_ATTRIBUTE;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT:
+ return LOGICAL_LOCATION_KIND_TEXT;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT:
+ return LOGICAL_LOCATION_KIND_COMMENT;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION:
+ return LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD:
+ return LOGICAL_LOCATION_KIND_DTD;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION:
+ return LOGICAL_LOCATION_KIND_DECLARATION;
+
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT:
+ return LOGICAL_LOCATION_KIND_OBJECT;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY:
+ return LOGICAL_LOCATION_KIND_ARRAY;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY:
+ return LOGICAL_LOCATION_KIND_PROPERTY;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE:
+ return LOGICAL_LOCATION_KIND_VALUE;
}
}
if (diag_logical_loc && diag_logical_loc != mgr.get_prev_diag_logical_loc ())
{
pp_set_prefix (pp, nullptr);
+
+ /* This macro is used to ensure that all format strings are visible to gettext
+ and checked at compile time. */
+
+#define CASE(KIND, MSGID) \
+ case KIND: \
+ if (const char *name \
+ = diag_logical_loc->m_fully_qualified_name.get_str ()) \
+ { \
+ pp_printf (pp, (MSGID), name); \
+ pp_character (pp, ':'); \
+ pp_newline (pp); \
+ } \
+ break;
+
switch (diag_logical_loc->m_kind)
{
default:
break;
- case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
- if (const char *name
- = diag_logical_loc->m_fully_qualified_name.get_str ())
- {
- pp_printf (pp, _("In function %qs"), name);
- pp_character (pp, ':');
- pp_newline (pp);
- }
- break;
- // TODO: handle other cases
+
+ /* Kinds within executable code. */
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION, _("In function %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER, _("In member %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE, _("In module %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_NAMESPACE, _("In namespace %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE, _("In type %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE,
+ _("In return type %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER, _("In parameter %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE, _("In variable %qs"))
+
+ /* Kinds within XML or HTML documents. */
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT, _("In element %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE, _("In attribute %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT, _("In text %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT, _("In comment %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION,
+ _("In processing instruction %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD, _("In DTD %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION,
+ _("In declaration %qs"))
+
+ /* Kinds within JSON documents. */
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT, _("In JSON object %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY, _("In JSON array %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY,
+ _("In JSON property %qs"))
+ CASE(DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE, _("In JSON value %qs"))
}
+
+#undef CASE
}
pp_set_prefix (pp,
text_output.build_prefix (*info));
{
default:
gcc_unreachable ();
+
case DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION:
fprintf (out, "function");
break;
case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE:
fprintf (out, "variable");
break;
+
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT:
+ fprintf (out, "element");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE:
+ fprintf (out, "attribute");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT:
+ fprintf (out, "text");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT:
+ fprintf (out, "comment");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION:
+ fprintf (out, "processing_instruction");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD:
+ fprintf (out, "dtd");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION:
+ fprintf (out, "declaration");
+ break;
+
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT:
+ fprintf (out, "object");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY:
+ fprintf (out, "array");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY:
+ fprintf (out, "property");
+ break;
+ case DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE:
+ fprintf (out, "value");
+ break;
}
if (auto parent = loc->m_parent)
{
enum diagnostic_logical_location_kind_t
{
+ /* Kinds within executable code. */
DIAGNOSTIC_LOGICAL_LOCATION_KIND_FUNCTION,
DIAGNOSTIC_LOGICAL_LOCATION_KIND_MEMBER,
DIAGNOSTIC_LOGICAL_LOCATION_KIND_MODULE,
DIAGNOSTIC_LOGICAL_LOCATION_KIND_TYPE,
DIAGNOSTIC_LOGICAL_LOCATION_KIND_RETURN_TYPE,
DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER,
- DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE,
+
+ /* Kinds within XML or HTML documents. */
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION,
+
+ /* Kinds within JSON documents. */
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE
};
/* A "diagnostic" is an opaque bundle of state for a particular
{ "parameter",
DIAGNOSTIC_LOGICAL_LOCATION_KIND_PARAMETER },
{ "variable",
- DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE } };
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_VARIABLE },
+
+ { "element",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ELEMENT },
+ { "attribute",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ATTRIBUTE },
+ { "text",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_TEXT },
+ { "comment",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_COMMENT },
+ { "processingInstruction",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION },
+ { "dtd",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_DTD },
+ { "declaration",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_DECLARATION },
+
+ { "object",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT },
+ { "array",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY },
+ { "property",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY },
+ { "value",
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE },
+ };
auto result
= get_value_from_json_string<enum diagnostic_logical_location_kind_t>
(*kind_str, kind_prop, kind_values, ARRAY_SIZE (kind_values));
{
LOGICAL_LOCATION_KIND_UNKNOWN,
+ /* Kinds within executable code. */
LOGICAL_LOCATION_KIND_FUNCTION,
LOGICAL_LOCATION_KIND_MEMBER,
LOGICAL_LOCATION_KIND_MODULE,
LOGICAL_LOCATION_KIND_TYPE,
LOGICAL_LOCATION_KIND_RETURN_TYPE,
LOGICAL_LOCATION_KIND_PARAMETER,
- LOGICAL_LOCATION_KIND_VARIABLE
+ LOGICAL_LOCATION_KIND_VARIABLE,
+
+ /* Kinds within XML or HTML documents. */
+ LOGICAL_LOCATION_KIND_ELEMENT,
+ LOGICAL_LOCATION_KIND_ATTRIBUTE,
+ LOGICAL_LOCATION_KIND_TEXT,
+ LOGICAL_LOCATION_KIND_COMMENT,
+ LOGICAL_LOCATION_KIND_PROCESSING_INSTRUCTION,
+ LOGICAL_LOCATION_KIND_DTD,
+ LOGICAL_LOCATION_KIND_DECLARATION,
+
+ /* Kinds within JSON documents. */
+ LOGICAL_LOCATION_KIND_OBJECT,
+ LOGICAL_LOCATION_KIND_ARRAY,
+ LOGICAL_LOCATION_KIND_PROPERTY,
+ LOGICAL_LOCATION_KIND_VALUE
};
/* We want to efficiently support passing around logical locations in the
--- /dev/null
+from sarif import *
+
+import pytest
+
+@pytest.fixture(scope='function', autouse=True)
+def sarif():
+ return sarif_from_env()
+
+def test_sarif_output_with_logical_location(sarif):
+ schema = sarif['$schema']
+ assert schema == 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json'
+
+ version = sarif['version']
+ assert version == '2.1.0'
+
+ runs = sarif['runs']
+ run = runs[0]
+
+ tool = run['tool']
+ assert tool['driver']['name'] == 'test-nested-logical-locations-json.c.exe'
+
+ results = run['results']
+ assert len(results) == 2
+
+ result = results[0]
+ assert result['ruleId'] == 'warning'
+ assert result['level'] == 'warning'
+ assert result['message']['text'] == "product ID is blank"
+ assert len(result['locations']) == 1
+ location = result['locations'][0]
+ assert len(location['logicalLocations']) == 1
+ logical_loc = location['logicalLocations'][0]
+ assert logical_loc['index'] == 3
+ assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1'
+
+ result = results[1]
+ assert result['ruleId'] == 'warning'
+ assert result['level'] == 'warning'
+ assert result['message']['text'] == "value is negative"
+ assert len(result['locations']) == 1
+ location = result['locations'][0]
+ assert len(location['logicalLocations']) == 1
+ logical_loc = location['logicalLocations'][0]
+ assert logical_loc['index'] == 4
+ assert logical_loc['fullyQualifiedName'] == '/orders/0/total'
+
+ # Check theRun.logicalLocations
+ assert 'logicalLocations' in run
+ assert len(run['logicalLocations']) == 5
+ logical_loc = run['logicalLocations'][0]
+ assert logical_loc['name'] == 'orders'
+ assert logical_loc['fullyQualifiedName'] == '/orders'
+ assert logical_loc['kind'] == 'array'
+ assert logical_loc['index'] == 0
+ logical_loc = run['logicalLocations'][1]
+ assert logical_loc['name'] == '0'
+ assert logical_loc['fullyQualifiedName'] == '/orders/0'
+ assert logical_loc['kind'] == 'object'
+ assert logical_loc['parentIndex'] == 0
+ assert logical_loc['index'] == 1
+ logical_loc = run['logicalLocations'][2]
+ assert logical_loc['name'] == 'productIds'
+ assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds'
+ assert logical_loc['kind'] == 'array'
+ assert logical_loc['parentIndex'] == 1
+ assert logical_loc['index'] == 2
+ logical_loc = run['logicalLocations'][3]
+ assert logical_loc['name'] == '1'
+ assert logical_loc['fullyQualifiedName'] == '/orders/0/productIds/1'
+ assert logical_loc['kind'] == 'value'
+ assert logical_loc['parentIndex'] == 2
+ assert logical_loc['index'] == 3
+ logical_loc = run['logicalLocations'][4]
+ assert logical_loc['name'] == 'total'
+ assert logical_loc['fullyQualifiedName'] == '/orders/0/total'
+ assert logical_loc['kind'] == 'property'
+ assert logical_loc['parentIndex'] == 1
+ assert logical_loc['index'] == 4
+
--- /dev/null
+/* Example of nested logical locations, based on the JSON example in
+ SARIF v2.1.0, 3.33.7 "kind" property;
+ though see https://github.com/oasis-tcs/sarif-spec/issues/670
+
+ Intended output is similar to:
+
+In JSON value '/orders/0/productIds/1':
+PATH/test-nested-logical-locations-json.c:28:32: warning: product ID is blank
+ 28 | "productIds": [ "A-101", "", "A-223" ],
+ | ^~
+In JSON property '/orders/0/total':
+PATH/test-nested-logical-locations-json.c:29:16: warning: value is negative
+ 29 | "total": "-3.25"
+ | ^~~~~~~
+
+ along with the equivalent in SARIF, capturing JSON structure
+ as nested logical locations. */
+
+#include "libgdiagnostics.h"
+#include "test-helpers.h"
+
+/* Placeholder source:
+_________1111111111222222222233333333334444444444
+1234567890123456789012345678901234567890123456789
+{
+ "orders": [
+ {
+ "productIds": [ "A-101", "", "A-223" ],
+ "total": "-3.25"
+ }
+ ]
+}
+*/
+const int start_line_num = __LINE__ - 9;
+const int line_num_of_product_ids = start_line_num + 3;
+const int line_num_of_total = line_num_of_product_ids + 1;
+
+#include <assert.h>
+
+int
+main ()
+{
+ begin_test ("test-nested-logical-locations-json.c.exe",
+ "test-nested-logical-locations-json.c.sarif",
+ __FILE__, "c");
+
+ /* Create tree of logical locations. */
+ /* begin quoted source */
+ const diagnostic_logical_location *logical_loc_orders_arr
+ = diagnostic_manager_new_logical_location (diag_mgr,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY,
+ NULL, /* parent */
+ "orders",
+ "/orders",
+ NULL);
+ const diagnostic_logical_location *logical_loc_order_0
+ = diagnostic_manager_new_logical_location (diag_mgr,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_OBJECT,
+ logical_loc_orders_arr, /* parent */
+ "0",
+ "/orders/0",
+ NULL);
+ const diagnostic_logical_location *logical_loc_product_ids
+ = diagnostic_manager_new_logical_location (diag_mgr,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_ARRAY,
+ logical_loc_order_0, /* parent */
+ "productIds",
+ "/orders/0/productIds",
+ NULL);
+ const diagnostic_logical_location *logical_loc_element_1
+ = diagnostic_manager_new_logical_location (diag_mgr,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_VALUE,
+ logical_loc_product_ids, /* parent */
+ "1",
+ "/orders/0/productIds/1",
+ NULL);
+ const diagnostic_logical_location *logical_loc_total
+ = diagnostic_manager_new_logical_location (diag_mgr,
+ DIAGNOSTIC_LOGICAL_LOCATION_KIND_PROPERTY,
+ logical_loc_order_0, /* parent */
+ "total",
+ "/orders/0/total",
+ NULL);
+ /* end quoted source */
+
+ {
+ const int line_num = line_num_of_product_ids;
+ const diagnostic_physical_location *loc_start
+ = diagnostic_manager_new_location_from_file_line_column (diag_mgr,
+ main_file,
+ line_num,
+ 32);
+ const diagnostic_physical_location *loc_end
+ = diagnostic_manager_new_location_from_file_line_column (diag_mgr,
+ main_file,
+ line_num,
+ 33);
+ const diagnostic_physical_location *loc_range
+ = diagnostic_manager_new_location_from_range (diag_mgr,
+ loc_start,
+ loc_start,
+ loc_end);
+
+ diagnostic *d = diagnostic_begin (diag_mgr,
+ DIAGNOSTIC_LEVEL_WARNING);
+ diagnostic_set_location (d, loc_range);
+
+ diagnostic_set_logical_location (d, logical_loc_element_1);
+
+ diagnostic_finish (d, "product ID is blank");
+ }
+ {
+ const int line_num = line_num_of_total;
+ const diagnostic_physical_location *loc_start
+ = diagnostic_manager_new_location_from_file_line_column (diag_mgr,
+ main_file,
+ line_num,
+ 16);
+ const diagnostic_physical_location *loc_end
+ = diagnostic_manager_new_location_from_file_line_column (diag_mgr,
+ main_file,
+ line_num,
+ 22);
+ const diagnostic_physical_location *loc_range
+ = diagnostic_manager_new_location_from_range (diag_mgr,
+ loc_start,
+ loc_start,
+ loc_end);
+
+ diagnostic *d = diagnostic_begin (diag_mgr,
+ DIAGNOSTIC_LEVEL_WARNING);
+ diagnostic_set_location (d, loc_range);
+
+ diagnostic_set_logical_location (d, logical_loc_total);
+
+ diagnostic_finish (d, "value is negative");
+ }
+
+ return end_test ();
+}
+
+/* Check the output from the text sink. */
+/* { dg-begin-multiline-output "" }
+In JSON value '/orders/0/productIds/1':
+ { dg-end-multiline-output "" } */
+/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:28:32: warning: product ID is blank" } */
+/* { dg-begin-multiline-output "" }
+ 28 | "productIds": [ "A-101", "", "A-223" ],
+ | ^~
+ { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+In JSON property '/orders/0/total':
+ { dg-end-multiline-output "" } */
+/* { dg-regexp "\[^\n\r\]+test-nested-logical-locations-json.c:29:16: warning: value is negative" } */
+/* { dg-begin-multiline-output "" }
+ 29 | "total": "-3.25"
+ | ^~~~~~~
+ { dg-end-multiline-output "" } */
+
+/* Verify that some JSON was written to a file with the expected name:
+ { dg-final { verify-sarif-file } } */
+
+/* Use a Python script to verify various properties about the generated
+ .sarif file:
+ { dg-final { run-sarif-pytest test-nested-logical-locations-json.c "test-nested-logical-locations-json-c.py" } } */
--- /dev/null
+/* Adapted from the JSON example in SARIF v2.1.0, 3.33.7 "kind" property;
+ see https://github.com/oasis-tcs/sarif-spec/issues/670 */
+{
+ "version": "2.1.0",
+ "runs": [
+ {
+ "tool": {
+ "driver": {
+ "name": "example JSON scanner"
+ }
+ },
+ "results": [
+ {
+ "message": {"text": "product ID is blank"},
+ "locations": [
+ {
+ "logicalLocations": [
+ {
+ "fullyQualifiedName": "/orders/0/productIds/1",
+ "index": 3
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "message": {"text": "value is negative"},
+ "locations": [
+ {
+ "logicalLocations": [
+ {
+ "fullyQualifiedName": "/orders/0/total",
+ "index": 4
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "logicalLocations": [
+ {
+ "name": "orders",
+ "fullyQualifiedName": "/orders",
+ "kind": "array"
+ },
+ {
+ "name": "0",
+ "fullyQualifiedName": "/orders/0",
+ "kind": "object",
+ "parentIndex": 0
+ },
+ {
+ "name": "productIds",
+ "fullyQualifiedName": "/orders/0/productIds",
+ "kind": "array",
+ "parentIndex": 1
+ },
+ {
+ "name": "1",
+ "fullyQualifiedName": "/orders/0/productIds/1",
+ "kind": "value",
+ "parentIndex": 2
+ },
+ {
+ "name": "total",
+ "fullyQualifiedName": "/orders/0/total",
+ "kind": "property",
+ "parentIndex": 1
+ }
+ ]
+ }
+ ]
+}
+
+/* { dg-begin-multiline-output "" }
+In JSON value '/orders/0/productIds/1':
+example JSON scanner: warning: product ID is blank
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+In JSON property '/orders/0/total':
+example JSON scanner: warning: value is negative
+ { dg-end-multiline-output "" } */
--- /dev/null
+/* Adapted from the XML example in SARIF v2.1.0, 3.33.7 "kind" property;
+ see also https://github.com/oasis-tcs/sarif-spec/issues/669 */
+{
+ "version": "2.1.0",
+ "runs": [
+ {
+ "tool": {
+ "driver": {
+ "name": "example XML scanner"
+ }
+ },
+ "results": [
+ {
+ "message": {"text": "empty value"},
+ "locations": [
+ {
+ "logicalLocations": [
+ {
+ "fullyQualifiedName": "/orders/order[1]/@number",
+ "index": 2
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "message": {"text": "total is negative"},
+ "locations": [
+ {
+ "logicalLocations": [
+ {
+ "fullyQualifiedName": "/orders/order[1]/total/text()",
+ "index": 3
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "logicalLocations": [
+ {
+ "name": "orders",
+ "fullyQualifiedName": "/orders",
+ "kind": "element"
+ },
+ {
+ "name": "order[1]",
+ "fullyQualifiedName": "/orders/order[1]",
+ "kind": "element",
+ "parentIndex": 0
+ },
+ {
+ "name": "number",
+ "fullyQualifiedName": "/orders/order[1]/@number",
+ "kind": "attribute",
+ "parentIndex": 1
+ },
+ {
+ "name": "text",
+ "fullyQualifiedName": "/orders/order[1]/total/text()",
+ "kind": "text",
+ "parentIndex": 1
+ }
+ ]
+ }
+ ]
+}
+
+/* { dg-begin-multiline-output "" }
+In attribute '/orders/order[1]/@number':
+example XML scanner: warning: empty value
+ { dg-end-multiline-output "" } */
+
+/* { dg-begin-multiline-output "" }
+In text '/orders/order[1]/total/text()':
+example XML scanner: warning: total is negative
+ { dg-end-multiline-output "" } */