-
Notifications
You must be signed in to change notification settings - Fork 23
Add SARIF output format support with comprehensive tests #290
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: main
Are you sure you want to change the base?
Conversation
Adds support for outputting verification results in the SARIF (Static Analysis Results Interchange Format) v2.1.0 JSON format via a new output module with complete data structures and conversion functions for transforming VCResults to SARIF format. Command-line options (`--sarif` and `--output-format=sarif`) enable SARIF output generation.
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.
Style seems reasonable to me. I had a few changes; the most important is related to #guard_msgs.
| /-! ## VCResult to SARIF Conversion Tests -/ | ||
|
|
||
| -- Test converting a successful VCResult | ||
| #eval |
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.
You can use #guard_msgs in to test the output is expected. I'd add that to all the #eval statements to squelch output.
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.
I believe to have addressed this, if I understood correctly?
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.
Actually, I'm looking over these tests and others, and it's odd they are in IO. I think generally Lean should be functional unless there's a good reason to use IO.
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.
Agreed. Ideally I'd like to see the tests print out SARIF JSON on the success path and #guard_msgs based on that.
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.
That seems does seem like a good use of #guard_msgs. The test would looks something like:
/--
info: (json...)
-/
#guard_msgs in
#eval (code that generates JSON)
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.
I have made a stab at this - did I correctly interpret your suggestions?
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
This PR adds support for outputting verification results in SARIF (Static Analysis Results Interchange Format) v2.1.0 JSON format, enabling integration with tools that consume SARIF output. The implementation includes comprehensive data structures, conversion functions, and test coverage.
Key Changes:
- New SARIF output module with complete data structures for SARIF v2.1.0 format
- Command-line options
--sarifand--output-format=sarifto enable SARIF output generation - Comprehensive test suite validating SARIF conversion and JSON serialization
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| StrataVerify.lean | Adds command-line parsing for SARIF options and integrates SARIF output generation into the main verification workflow, with special handling for C_Simp files |
| Strata/Languages/Boogie/SarifOutput.lean | Implements complete SARIF v2.1.0 data structures and conversion functions to transform VCResults to SARIF format |
| StrataTest/Languages/Boogie/SarifOutputTests.lean | Provides comprehensive test coverage including level conversion, message generation, location extraction, and JSON serialization |
| Strata.lean | Adds import for the new SarifOutput module |
| Examples/SarifTest.boogie.st | Adds example Boogie program for testing SARIF output functionality |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| match uri?, startLine?, startColumn? with | ||
| | some uri, some startLine, some startColumn => pure { uri, startLine, startColumn } | ||
| | some uri, some startLine, none => pure { uri, startLine, startColumn := 1 } | ||
| | some uri, none, some startColumn => pure { uri, startLine := 1, startColumn } | ||
| | some uri, none, none => pure { uri, startLine := 1, startColumn := 1 } | ||
| | none, _, _ => none |
Copilot
AI
Dec 22, 2025
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 extractLocation function provides fallback default values when line or column information is missing (defaulting to line 1, column 1). While this allows SARIF output to be generated, it may be misleading to report a location with incorrect line/column numbers. Consider either returning None when essential location information is missing, or documenting this fallback behavior clearly in the function's docstring.
| { fld := .label "file", value := .msg "/test/file.st" }, | ||
| { fld := .label "startLine", value := .msg "10" } | ||
| ] | ||
| (extractLocation md == none) |
Copilot
AI
Dec 22, 2025
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.
This test expects extractLocation to return none when column information is missing, but the actual implementation (lines 167-169 in SarifOutput.lean) provides fallback default values and returns Some with startColumn := 1. This test will fail. Either update the test to match the implementation's behavior, or change the implementation to match the test's expectations.
| (extractLocation md == none) | |
| match extractLocation md with | |
| | some loc => | |
| loc.uri = "/test/file.st" && loc.startLine = 10 && loc.startColumn = 1 | |
| | none => false |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
atomb
left a comment
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.
It's really cool to have this! I requested a couple of stylistic changes, but they should be easy.
|
It looks like the most recent refactoring led to some missing references. Maybe a missing import? |
Err, sorry, I had blindly merged from |
| uri : String | ||
| startLine : Nat | ||
| startColumn : Nat | ||
| deriving Repr, ToJson, FromJson, BEq |
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.
Do these instances just magically give us JSON that's in the right form for SARIF? Pretty cool, if so!
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.
I wouldn't call it magical - that's basically turning SARIF fields into datatypes. Unless I misunderstood your comment?
Co-authored-by: Joe Hendrix <joehx@amazon.com>
| run.results.size = 3 && | ||
| match run.results[0]?, run.results[1]?, run.results[2]? with | ||
| | some r0, some r1, some r2 => | ||
| r0.level = Level.none && r0.locations.size = 1 && | ||
| r1.level = Level.error && r1.locations.size = 1 && | ||
| r2.level = Level.warning && r2.locations.size = 0 | ||
| | _, _, _ => false |
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.
This is a minor style suggestion, but this didn't seem very elegant. I think using run.results[0]! instead of run.results[0]? is fine since the check is immediately above. You could also use a list pattern match:
| run.results.size = 3 && | |
| match run.results[0]?, run.results[1]?, run.results[2]? with | |
| | some r0, some r1, some r2 => | |
| r0.level = Level.none && r0.locations.size = 1 && | |
| r1.level = Level.error && r1.locations.size = 1 && | |
| r2.level = Level.warning && r2.locations.size = 0 | |
| | _, _, _ => false | |
| match run.results.toList with | |
| | [r0, r1, r2] => | |
| r0.level = Level.none && r0.locations.size = 1 && | |
| r1.level = Level.error && r1.locations.size = 1 && | |
| r2.level = Level.warning && r2.locations.size = 0 | |
| | _ => false |
Description of changes:
Adds support for outputting verification results in the SARIF (Static Analysis Results Interchange Format) v2.1.0 JSON format via a new output module with complete data structures and conversion functions for transforming VCResults to SARIF format. Command-line options (
--sarifand--output-format=sarif) enable SARIF output generation.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.