return false;
}
+struct embedded_link
+{
+ std::string text;
+ std::string destination;
+};
+
+/* If ITER_SRC starts with an embedded link as per §3.11.6, advance ITER_SRC
+ to immediately beyond the link, and return the link.
+
+ Otherwise, leave ITER_SRC untouched and return nullptr. */
+
+static std::unique_ptr<embedded_link>
+maybe_consume_embedded_link (const char *&iter_src)
+{
+ if (*iter_src != '[')
+ return nullptr;
+
+ /* This *might* be an embedded link.
+ See §3.11.6 ("Messages with embedded links") and
+ https://github.com/oasis-tcs/sarif-spec/issues/657 */
+
+ /* embedded link = "[", link text, "](", link destination, ")"; */
+
+ embedded_link result;
+
+ /* Try to get the link text. */
+ const char *iter = iter_src + 1;
+ while (char ch = *(iter++))
+ {
+ if (ch == '\\')
+ {
+ char next_ch = *iter;
+ switch (next_ch)
+ {
+ case '\\':
+ case '[':
+ case ']':
+ /* escaped link character = "\" | "[" | "]"; */
+ result.text += next_ch;
+ iter++;
+ continue;
+
+ default:
+ /* Malformed link text; assume this is not an
+ embedded link. */
+ return nullptr;
+ }
+ }
+ else if (ch == ']')
+ /* End of link text. */
+ break;
+ else
+ result.text += ch;
+ }
+
+ if (*iter++ != '(')
+ return nullptr;
+
+ /* Try to get the link destination. */
+ while (1)
+ {
+ char ch = *(iter++);
+ if (ch == '\0')
+ {
+ /* String ended before terminating ')'.
+ Assume this is not an embedded link. */
+ return nullptr;
+ }
+ else if (ch == ')')
+ /* Terminator. */
+ break;
+ else
+ result.destination += ch;
+ }
+
+ iter_src = iter;
+ return ::make_unique<embedded_link> (std::move (result));
+}
+
/* Lookup the plain text string within a result.message (§3.27.11),
- and substitute for any placeholders (§3.11.5).
+ and substitute for any placeholders (§3.11.5) and handle any
+ embedded links (§3.11.6).
Limitations:
- - we don't yet support embedded links
+ - we don't preserve destinations within embedded links
MESSAGE_OBJ is "theMessage"
RULE_OBJ is "theRule". */
return label_text::borrow (nullptr);
}
}
+ else if (auto link = maybe_consume_embedded_link (iter_src))
+ {
+ accum += link->text;
+ /* TODO: use the destination. */
+ /* TODO: potentially could try to convert
+ intra-sarif links into event ids. */
+ }
else
{
accum += ch;
--- /dev/null
+{"$schema": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json",
+ "version": "2.1.0",
+ "runs": [{"tool": {"driver": {"name": "hand-written"}},
+ "results": [{"message": {"text": "001: this is a test"},
+ "locations": []},
+/* { dg-begin-multiline-output "" }
+hand-written: warning: 001: this is a test
+ { dg-end-multiline-output "" } */
+
+ /* Without the fix from https://github.com/oasis-tcs/sarif-spec/issues/656 */
+ {"message": {"text": "002: Prohibited term used in [para\\[0\\]\\\\spans\\[2\\](1)."},
+ "locations": []},
+/* { dg-begin-multiline-output "" }
+hand-written: warning: 002: Prohibited term used in [para\[0\]\\spans\[2\](1).
+ { dg-end-multiline-output "" } */
+
+ /* With the fix from https://github.com/oasis-tcs/sarif-spec/issues/656 */
+ {"message": {"text": "003: Prohibited term used in [para\\[0\\]\\\\spans\\[2\\]](1)."},
+ "locations": []}
+/* { dg-begin-multiline-output "" }
+hand-written: warning: 003: Prohibited term used in para[0]\spans[2].
+ { dg-end-multiline-output "" } */
+
+]}]}
+
"nestingLevel": 1,
"executionOrder": 5}]}]}]}]}]}
// TODO: show the CWEs
-// TODO: fix URL in message
/* { dg-begin-multiline-output "" }
In function 'callee_1':
| 5 | *ptr = 42;
| | ~~~~~~~~~~
| | |
- | | (7) ‘ptr’ could be NULL: unchecked value from [(4)](sarif:/runs/0/results/0/codeFlows/0/threadFlows/0/locations/3)
+ | | (7) ‘ptr’ could be NULL: unchecked value from (4)
|
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
38 | free (ptr);
| ~~~~~~~~~~~
| |
- | (5) second ‘free’ here; first ‘free’ was at [(4)](sarif:/runs/0/results/1/codeFlows/0/threadFlows/0/locations/3)
+ | (5) second ‘free’ here; first ‘free’ was at (4)
{ dg-end-multiline-output "" } */