-
Notifications
You must be signed in to change notification settings - Fork 285
Add SARIF output support via --sarif-ui option #8835
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Implements Static Analysis Results Interchange Format (SARIF) support as an extension of the existing json-ui option. Fixes: diffblue#6851
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds a new --sarif-ui user-interface mode intended to emit SARIF 2.1.0 JSON, extending existing JSON UI plumbing to output verification results as SARIF “results” entries.
Changes:
- Extend
ui_message_handlertwith a newSARIF_UImode and streaming helpersarif_output(...). - Convert goto-checker property reporting to emit SARIF result objects.
- Add a new regression suite (
regression/cbmc-sarif-ui) to validate SARIF JSON structure.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/util/ui_message.h | Adds SARIF_UI enum value, sarif_output(...), and tracking state. |
| src/util/ui_message.cpp | Emits SARIF log wrapper on stdout; routes general messages to stderr in SARIF mode. |
| src/pointer-analysis/show_value_sets.cpp | Treats SARIF like JSON for value-set output. |
| src/json/json_interface.h | Registers --sarif-ui in option/help macros. |
| src/goto-symex/show_vcc.cpp | Treats SARIF like JSON for --show-vcc output. |
| src/goto-symex/show_program.cpp | Treats SARIF like JSON for --show-byte-ops output. |
| src/goto-programs/show_symbol_table.cpp | Treats SARIF like JSON UI for symbol table output. |
| src/goto-programs/show_properties.cpp | Adds SARIF case (currently UNREACHABLE) in property printing. |
| src/goto-programs/show_goto_functions.cpp | Adds SARIF case for showing goto functions (JSON-like output). |
| src/goto-programs/loop_ids.cpp | Adds SARIF case for loop IDs (falls back to PLAIN). |
| src/goto-programs/class_hierarchy.cpp | Marks SARIF as unimplemented for class hierarchy output. |
| src/goto-instrument/show_locations.cpp | Marks SARIF as unreachable in locations output. |
| src/goto-diff/goto_diff_base.cpp | Adds SARIF “not supported” error path. |
| src/goto-checker/report_util.cpp | Emits SARIF results for properties via sarif_result(...) + sarif_output(...). |
| src/goto-checker/properties.h | Declares sarif_result(...). |
| src/goto-checker/properties.cpp | Implements SARIF result object construction (ruleId/level/message/locations). |
| src/goto-checker/cover_goals_report_util.cpp | Routes SARIF case through existing JSON goal output. |
| src/goto-checker/bmc_util.cpp | Emits SARIF result for error trace (last step). |
| src/cbmc/cbmc_parse_options.cpp | Allows --sarif-ui for some JSON-only modes; updates help text for array constraints. |
| src/cbmc/c_test_input_generator.cpp | Adds SARIF case (prints test suite text). |
| jbmc/src/jbmc/jbmc_parse_options.cpp | Adds SARIF case for dumping options as JSON object. |
| regression/CMakeLists.txt | Adds cbmc-sarif-ui regression subdirectory. |
| regression/cbmc-sarif-ui/Makefile | Adds regression make target and SARIF validation invocation. |
| regression/cbmc-sarif-ui/CMakeLists.txt | Adds CTest entries for SARIF regression + validation script. |
| regression/cbmc-sarif-ui/validate_sarif.py | Validates SARIF top-level schema/runs/results structure. |
| regression/cbmc-sarif-ui/test_sarif_valid.sh | Runs CBMC with --sarif-ui on test cases and validates output. |
| regression/cbmc-sarif-ui/success/success.desc | Adds expected-output checks for SARIF success case. |
| regression/cbmc-sarif-ui/success/success.c | Test input for success case. |
| regression/cbmc-sarif-ui/failure/failure.desc | Adds expected-output checks for SARIF failure case. |
| regression/cbmc-sarif-ui/failure/failure.c | Test input for failure case. |
| regression/cbmc-sarif-ui/bounds/bounds.desc | Adds expected-output checks for SARIF bounds failures. |
| regression/cbmc-sarif-ui/bounds/bounds.c | Test input for bounds failures. |
| regression/cbmc-sarif-ui/mixed/mixed.desc | Adds expected-output checks for mixed pass/fail SARIF output. |
| regression/cbmc-sarif-ui/mixed/mixed.c | Test input for mixed case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case ui_message_handlert::uit::SARIF_UI: | ||
| show_symbol_table_brief_json_ui(symbol_table, ui); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue as above: show_symbol_table_brief_json_ui depends on ui.get_json_stream(), but in SARIF_UI json_stream is never initialized, so this will trip the PRECONDITION and terminate. SARIF_UI should not reuse JSON_UI streaming helpers unless the JSON stream is set up for SARIF as well.
| case ui_message_handlert::uit::XML_UI: | ||
| { | ||
| msg.error() << "XML output not supported yet" << messaget::eom; | ||
| } | ||
| case ui_message_handlert::uit::SARIF_UI: | ||
| { | ||
| msg.error() << "SARIF output not supported yet" << messaget::eom; | ||
| } |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing break; after the XML_UI case causes fallthrough into SARIF_UI, so --xml-ui will emit both the XML and SARIF 'not supported' errors. Add an explicit break (or [[fallthrough]] if intentional) after the XML_UI block.
| out << "{\n"; | ||
| out << " \"$schema\": " | ||
| "\"https://json.schemastore.org/sarif-2.1.0.json\",\n"; | ||
| out << " \"version\": \"2.1.0\",\n"; | ||
| out << " \"runs\": [\n"; | ||
| out << " {\n"; | ||
| out << " \"tool\": {\n"; | ||
| out << " \"driver\": {\n"; | ||
| out << " \"name\": \"" << program << "\",\n"; | ||
| out << " \"version\": \"" << CBMC_VERSION << "\",\n"; | ||
| out | ||
| << " \"informationUri\": \"https://www.cprover.org/cbmc/\"\n"; | ||
| out << " }\n"; | ||
| out << " },\n"; | ||
| out << " \"results\": [\n"; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SARIF header is constructed by manually concatenating strings and writing program directly into JSON. If program contains characters that require JSON escaping (quotes, backslashes, control chars), this will produce invalid SARIF/JSON output. Prefer building a json_objectt (or at least using json_stringt for string values) and serializing it, to guarantee proper escaping.
| case uit::SARIF_UI: | ||
| out << data; | ||
| flush(level); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When SARIF_UI is active, print(const jsont &) writes raw JSON to out (stdout). Any code path that logs structured JSON (including print(const structured_datat&) which calls to_json) will therefore interleave arbitrary JSON with the SARIF log wrapper, making stdout invalid SARIF. Consider rejecting print(jsont) / print(structured_datat) under SARIF_UI (INVARIANT), or redirecting them to stderr, or translating them into SARIF results via sarif_output.
| show_vcc_json(out, equation); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SARIF_UI branch reuses show_vcc_json(out, ...), but show_vcc_json emits output prefixed with ",\n" to append to the JSON_UI stream array format. Under --sarif-ui the UI handler has already written a SARIF log wrapper to stdout, so this will produce invalid mixed output. Consider rejecting SARIF_UI for --show-vcc (similar to XML_UI), or implement a SARIF-compatible representation instead of reusing the JSON_UI append format.
| show_vcc_json(out, equation); | |
| break; | |
| msg.error() << "SARIF UI not supported" << messaget::eom; | |
| return; |
| case ui_message_handlert::uit::SARIF_UI: | ||
| for(const auto &f : goto_functions.function_map) | ||
| show_loop_ids(ui_message_handlert::uit::PLAIN, f.first, f.second.body); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In SARIF_UI mode this falls back to PLAIN output written to stdout. However, ui_message_handlert emits a SARIF log wrapper to stdout in SARIF_UI mode, so mixing plain-text loop output into stdout will invalidate the SARIF JSON. Consider rejecting --sarif-ui for --show-loops, or routing this output to stderr / a separate file, or providing a SARIF representation for loop IDs.
| case ui_message_handlert::uit::SARIF_UI: | |
| for(const auto &f : goto_functions.function_map) | |
| show_loop_ids(ui_message_handlert::uit::PLAIN, f.first, f.second.body); | |
| break; | |
| case ui_message_handlert::uit::SARIF_UI: | |
| { | |
| // In SARIF_UI mode, ui_message_handlert emits SARIF JSON to stdout. | |
| // Redirect the PLAIN loop output to stderr to avoid corrupting SARIF. | |
| auto *const old_buf = std::cout.rdbuf(); | |
| std::cout.rdbuf(std::cerr.rdbuf()); | |
| for(const auto &f : goto_functions.function_map) | |
| show_loop_ids(ui_message_handlert::uit::PLAIN, f.first, f.second.body); | |
| std::cout.rdbuf(old_buf); | |
| break; | |
| } |
| cmdline.isset("xml-ui") || cmdline.isset("xml-interface") ? uit::XML_UI | ||
| : cmdline.isset("sarif-ui") ? uit::SARIF_UI | ||
| : cmdline.isset("json-ui") || cmdline.isset("json-interface") | ||
| ? uit::JSON_UI | ||
| : uit::PLAIN, |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI selection now prioritizes --sarif-ui over --json-interface. If a user passes both, the handler enters SARIF_UI mode but json_interface(...) will still attempt to read JSON from stdin and set json-ui, which is inconsistent and likely breaks the bidirectional JSON interface. Consider making --sarif-ui mutually exclusive with --json-interface (usage error), or giving --json-interface precedence over SARIF_UI.
| case ui_message_handlert::uit::SARIF_UI: | ||
| std::cout << value_set_analysis.output_json(goto_model); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SARIF_UI is handled here by emitting the same JSON output as JSON_UI to stdout. However, in SARIF_UI mode ui_message_handlert writes a SARIF log wrapper to stdout in its constructor/destructor, so this will produce invalid mixed output (SARIF header + value-set JSON). Either reject SARIF_UI for show_value_sets, or ensure this output is routed somewhere that doesn't corrupt the SARIF log (e.g., stderr), or provide a SARIF-compatible representation.
| UNREACHABLE; | ||
| break; | ||
|
|
||
| case ui_message_handlert::uit::SARIF_UI: | ||
| UNREACHABLE; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
show_properties(...) dispatches to show_properties_json(...) only when ui == JSON_UI. With --sarif-ui, it takes the non-JSON path and then hits case SARIF_UI: UNREACHABLE;, which will abort if a user runs --show-properties --sarif-ui (e.g., in cbmc or goto-instrument). Consider handling SARIF_UI explicitly in the top-level dispatch (similar to JSON_UI), or emitting a supported/unsupported error instead of UNREACHABLE.
| UNREACHABLE; | |
| break; | |
| case ui_message_handlert::uit::SARIF_UI: | |
| UNREACHABLE; | |
| msg.error() << "JSON UI is not supported for show_properties; " | |
| << "use --xml-ui or plain output instead" | |
| << messaget::eom; | |
| break; | |
| case ui_message_handlert::uit::SARIF_UI: | |
| msg.error() << "SARIF UI is not supported for show_properties; " | |
| << "use --xml-ui or plain output instead" | |
| << messaget::eom; |
| case ui_message_handlert::uit::SARIF_UI: | ||
| show_symbol_table_json_ui(symbol_table, ui); | ||
| break; |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the SARIF_UI branch this calls show_symbol_table_json_ui(..., ui), but show_symbol_table_json_ui requires ui.get_json_stream() which is only initialized for JSON_UI. With --sarif-ui, json_stream is null and the PRECONDITION in get_json_stream() will fail at runtime. Consider either (1) treating SARIF_UI as unsupported for this command and emitting a clear error, or (2) initializing/using a SARIF-specific output path that does not depend on the JSON stream array UI wrapper.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #8835 +/- ##
===========================================
- Coverage 80.00% 79.97% -0.03%
===========================================
Files 1700 1700
Lines 188252 188416 +164
Branches 73 73
===========================================
+ Hits 150613 150693 +80
- Misses 37639 37723 +84 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Implements Static Analysis Results Interchange Format (SARIF) support as an extension of the existing json-ui option.
Fixes: #6851