Skip to content

Commit 97e2f85

Browse files
Add SARIF output support via --sarif-result option
Add --sarif-result <file> option that writes a SARIF (Static Analysis Results Interchange Format) 2.1.0 log for verification results. Use --sarif-result - to write to stdout. Following ebmc's artefact-specific approach, SARIF output is handled by a standalone sarif_report() function rather than adding a new UI mode to ui_message_handlert. This avoids extending the switchboard pattern in the message handler. The option can be combined with any UI mode (--json-ui, --xml-ui, or plain text), producing both the normal output and a SARIF file. Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
1 parent eaaf029 commit 97e2f85

32 files changed

Lines changed: 546 additions & 13 deletions

doc/cprover-manual/cbmc-tutorial.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,44 @@ possible output format.
137137
cbmc file1.c --bounds-check --pointer-check --trace --xml-ui
138138
```
139139

140+
CBMC also supports [SARIF](https://sarifweb.azurewebsites.net/) (Static
141+
Analysis Results Interchange Format) output, which is widely supported by IDEs
142+
and CI systems:
143+
144+
```
145+
cbmc file1.c --bounds-check --pointer-check --sarif-ui
146+
```
147+
148+
This produces a JSON document conforming to the SARIF 2.1.0 schema, with each
149+
property reported as a SARIF result entry including rule identifier, severity
150+
level, message, and source location. For example:
151+
152+
```json
153+
{
154+
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
155+
"version": "2.1.0",
156+
"runs": [{
157+
"tool": {
158+
"driver": {
159+
"name": "CBMC ...",
160+
"informationUri": "https://www.cprover.org/cbmc/"
161+
}
162+
},
163+
"results": [{
164+
"ruleId": "main.assertion.1",
165+
"level": "error",
166+
"message": { "text": "assertion x > 0 (FAILURE)" },
167+
"locations": [{
168+
"physicalLocation": {
169+
"artifactLocation": { "uri": "example.c" },
170+
"region": { "startLine": 5 }
171+
}
172+
}]
173+
}]
174+
}]
175+
}
176+
```
177+
140178
## Verifying Modules
141179

142180
In the example above, we used a program that starts with a `main`

doc/man/cbmc.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,9 @@ use JSON\-formatted output
590590
\fB\-\-json\-interface\fR
591591
bi\-directional JSON interface
592592
.TP
593+
\fB\-\-sarif\-ui\fR
594+
use SARIF\-formatted output (Static Analysis Results Interchange Format)
595+
.TP
593596
\fB\-\-trace\-json\-extended\fR
594597
add rawLhs property to trace
595598
.TP

doc/man/jbmc.1

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,9 @@ use JSON\-formatted output
505505
\fB\-\-json\-interface\fR
506506
bi\-directional JSON interface
507507
.TP
508+
\fB\-\-sarif\-ui\fR
509+
use SARIF\-formatted output (Static Analysis Results Interchange Format)
510+
.TP
508511
\fB\-\-validate\-goto\-model\fR
509512
enable additional well\-formedness checks on the
510513
goto program

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,12 @@ int jbmc_parse_optionst::doit()
414414
case ui_message_handlert::uit::XML_UI:
415415
log.debug() << options.to_xml();
416416
break;
417+
case ui_message_handlert::uit::SARIF_UI:
418+
{
419+
json_objectt json_options{{"options", options.to_json()}};
420+
log.debug() << json_options;
421+
break;
422+
}
417423
}
418424

419425
register_language(new_ansi_c_language);

regression/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_subdirectory(cbmc-incr-smt2)
4040
add_subdirectory(cbmc-incr)
4141
add_subdirectory(cbmc-shadow-memory)
4242
add_subdirectory(cbmc-output-file)
43+
add_subdirectory(cbmc-sarif-ui)
4344
add_subdirectory(cbmc-with-incr)
4445
add_subdirectory(array-refinement-with-incr)
4546
add_subdirectory(goto-instrument-chc)

regression/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ DIRS = cbmc-shadow-memory \
1212
cpp \
1313
cbmc-concurrency \
1414
cbmc-cover \
15+
cbmc-sarif-ui \
1516
cbmc-incr-oneloop \
1617
cbmc-incr-smt2 \
1718
cbmc-incr \
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
add_test_pl_tests("$<TARGET_FILE:cbmc>")
2+
3+
add_test(
4+
NAME cbmc-sarif-validation
5+
COMMAND bash "${CMAKE_CURRENT_SOURCE_DIR}/test_sarif_valid.sh"
6+
"$<TARGET_FILE:cbmc>"
7+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
8+
)
9+
set_tests_properties(cbmc-sarif-validation PROPERTIES LABELS "CORE;CBMC")

regression/cbmc-sarif-ui/Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
default: test
2+
3+
include ../../src/config.inc
4+
include ../../src/common
5+
6+
test:
7+
@../test.pl -e -p -c ../../../src/cbmc/cbmc
8+
@bash test_sarif_valid.sh ../../src/cbmc/cbmc
9+
10+
tests.log: ../test.pl test
11+
12+
clean:
13+
find . -name '*.out' -execdir $(RM) '{}' \;
14+
$(RM) tests*.log
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int main()
2+
{
3+
int a[5];
4+
int i;
5+
a[i] = 1;
6+
return 0;
7+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
bounds.c
3+
--sarif-result - --bounds-check
4+
activate-multi-line-match
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
"\$schema": "https://json\.schemastore\.org/sarif-2\.1\.0\.json"
8+
"version": "2\.1\.0"
9+
"ruleId": "main\.array_bounds\.1"
10+
"ruleId": "main\.array_bounds\.2"
11+
"level": "error"
12+
"startLine": 5
13+
--
14+
--
15+
Checks that --sarif-result - produces multiple SARIF results for bounds-check failures.

0 commit comments

Comments
 (0)