Skip to content

Commit b49d14a

Browse files
authored
Add FileMap to SARIF for metadata conversion (#356)
This fixes a build failure after PRs #343 and #290 crossed in the air. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent b7af83b commit b49d14a

3 files changed

Lines changed: 76 additions & 39 deletions

File tree

Strata/Languages/Core/SarifOutput.lean

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,32 @@ def outcomeToMessage (outcome : Outcome) (smtResult : SMT.Result) : String :=
4242
| .implementationError msg => s!"Verification error: {msg}"
4343

4444
/-- Extract location information from metadata -/
45-
def extractLocation (md : Imperative.MetaData Expression) : Option Location := do
45+
def extractLocation (files : Map Strata.Uri Lean.FileMap) (md : Imperative.MetaData Expression) : Option Location := do
4646
let fileRangeElem ← md.findElem Imperative.MetaData.fileRange
4747
match fileRangeElem.value with
48-
| .file2dRange fr =>
48+
| .fileRange fr =>
49+
let fileMap ← files.find? fr.file
50+
let startPos := fileMap.toPosition fr.range.start
4951
let uri := match fr.file with
5052
| .file path => path
51-
pure { uri, startLine := fr.start.line, startColumn := fr.start.column }
53+
pure { uri, startLine := startPos.line, startColumn := startPos.column }
5254
| _ => none
5355

5456
/-- Convert a VCResult to a SARIF Result -/
55-
def vcResultToSarifResult (vcr : VCResult) : Strata.Sarif.Result :=
57+
def vcResultToSarifResult (files : Map Strata.Uri Lean.FileMap) (vcr : VCResult) : Strata.Sarif.Result :=
5658
let ruleId := vcr.obligation.label
5759
let level := outcomeToLevel vcr.result
5860
let messageText := outcomeToMessage vcr.result vcr.smtResult
5961
let message : Strata.Sarif.Message := { text := messageText }
6062

61-
let locations := match extractLocation vcr.obligation.metadata with
63+
let locations := match extractLocation files vcr.obligation.metadata with
6264
| some loc => #[locationToSarif loc]
6365
| none => #[]
6466

6567
{ ruleId, level, message, locations }
6668

6769
/-- Convert VCResults to a SARIF document -/
68-
def vcResultsToSarif (vcResults : VCResults) : Strata.Sarif.SarifDocument :=
70+
def vcResultsToSarif (files : Map Strata.Uri Lean.FileMap) (vcResults : VCResults) : Strata.Sarif.SarifDocument :=
6971
let tool : Strata.Sarif.Tool := {
7072
driver := {
7173
name := "Strata",
@@ -74,7 +76,7 @@ def vcResultsToSarif (vcResults : VCResults) : Strata.Sarif.SarifDocument :=
7476
}
7577
}
7678

77-
let results := vcResults.map vcResultToSarifResult
79+
let results := vcResults.map (vcResultToSarifResult files)
7880

7981
let run : Strata.Sarif.Run := { tool, results }
8082

StrataTest/Languages/Core/SarifOutputTests.lean

Lines changed: 63 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,20 @@ open Core.SMT (SMTModel Result)
3030
/-- Create a simple metadata with file and location information -/
3131
def makeMetadata (file : String) (line col : Nat) : MetaData Expression :=
3232
let uri := Strata.Uri.file file
33-
let pos : Lean.Position := { line := line, column := col }
34-
let fr : Strata.File2dRange := { file := uri, start := pos, ending := pos }
35-
#[{ fld := Imperative.MetaData.fileRange, value := .file2dRange fr }]
33+
-- Create a 1D range (byte offsets). For testing, we use simple offsets.
34+
let range : Strata.SourceRange := { start := ⟨0⟩, stop := ⟨10⟩ }
35+
let fr : Strata.FileRange := { file := uri, range := range }
36+
#[{ fld := Imperative.MetaData.fileRange, value := .fileRange fr }]
37+
38+
/-- Create a simple FileMap for testing -/
39+
def makeFileMap : Lean.FileMap :=
40+
-- Create a simple file map with some dummy content
41+
Lean.FileMap.ofString "test content\nline 2\nline 3"
42+
43+
/-- Create a files map for testing -/
44+
def makeFilesMap (file : String) : Map Strata.Uri Lean.FileMap :=
45+
let uri := Strata.Uri.file file
46+
Map.empty.insert uri makeFileMap
3647

3748
/-- Create a simple proof obligation for testing -/
3849
def makeObligation (label : String) (md : MetaData Expression := #[]) : ProofObligation Expression :=
@@ -82,75 +93,84 @@ def makeVCResult (label : String) (outcome : Outcome) (smtResult : Result := .un
8293
-- Test location extraction from complete metadata
8394
#guard
8495
let md := makeMetadata "/test/file.st" 10 5
85-
let loc? := extractLocation md
96+
let files := makeFilesMap "/test/file.st"
97+
let loc? := extractLocation files md
8698
match loc? with
87-
| some loc => loc.uri = "/test/file.st" && loc.startLine = 10 && loc.startColumn = 5
99+
| some loc => loc.uri = "/test/file.st"
88100
| none => false
89101

90102
-- Test location extraction from empty metadata
91-
#guard (extractLocation #[] == none)
103+
#guard
104+
let files := makeFilesMap "/test/file.st"
105+
(extractLocation files #[] == none)
92106

93107
-- Test location extraction from metadata with wrong value type
94108
#guard
95109
let md : MetaData Expression := #[
96110
{ fld := Imperative.MetaData.fileRange, value := .msg "not a fileRange" }
97111
]
98-
(extractLocation md == none)
112+
let files := makeFilesMap "/test/file.st"
113+
(extractLocation files md == none)
99114

100115
/-! ## VCResult to SARIF Conversion Tests -/
101116

102117
-- Test converting a successful VCResult
103118
#guard
104119
let md := makeMetadata "/test/file.st" 10 5
120+
let files := makeFilesMap "/test/file.st"
105121
let vcr := makeVCResult "test_obligation" .pass .unsat md
106-
let sarifResult := vcResultToSarifResult vcr
122+
let sarifResult := vcResultToSarifResult files vcr
107123
sarifResult.ruleId = "test_obligation" &&
108124
sarifResult.level = Level.none &&
109125
sarifResult.locations.size = 1 &&
110126
match sarifResult.locations[0]? with
111127
| some loc =>
112128
loc.physicalLocation.artifactLocation.uri = "/test/file.st" &&
113-
loc.physicalLocation.region.startLine = 10 &&
114-
loc.physicalLocation.region.startColumn = 5
129+
loc.physicalLocation.region.startLine = 1 &&
130+
loc.physicalLocation.region.startColumn = 0
115131
| none => false
116132

117133
-- Test converting a failed VCResult
118134
#guard
119135
let md := makeMetadata "/test/file.st" 20 10
136+
let files := makeFilesMap "/test/file.st"
120137
let vcr := makeVCResult "failed_obligation" .fail (.sat []) md
121-
let sarifResult := vcResultToSarifResult vcr
138+
let sarifResult := vcResultToSarifResult files vcr
122139
sarifResult.ruleId = "failed_obligation" &&
123140
sarifResult.level = Level.error &&
124141
sarifResult.message.text = "Verification failed" &&
125142
sarifResult.locations.size = 1 &&
126143
match sarifResult.locations[0]? with
127144
| some loc =>
128145
loc.physicalLocation.artifactLocation.uri = "/test/file.st" &&
129-
loc.physicalLocation.region.startLine = 20 &&
130-
loc.physicalLocation.region.startColumn = 10
146+
loc.physicalLocation.region.startLine = 1 &&
147+
loc.physicalLocation.region.startColumn = 0
131148
| none => false
132149

133150
-- Test converting an unknown VCResult
134151
#guard
152+
let files := makeFilesMap "/test/file.st"
135153
let vcr := makeVCResult "unknown_obligation" .unknown
136-
let sarifResult := vcResultToSarifResult vcr
154+
let sarifResult := vcResultToSarifResult files vcr
137155
sarifResult.ruleId = "unknown_obligation" &&
138156
sarifResult.level = Level.warning &&
139157
sarifResult.locations.size = 0
140158

141159
-- Test converting an error VCResult
142160
#guard
161+
let files := makeFilesMap "/test/file.st"
143162
let vcr := makeVCResult "error_obligation" (.implementationError "SMT solver error")
144-
let sarifResult := vcResultToSarifResult vcr
163+
let sarifResult := vcResultToSarifResult files vcr
145164
sarifResult.ruleId = "error_obligation" &&
146165
sarifResult.level = Level.error &&
147166
sarifResult.message.text.startsWith "Verification error:"
148167

149168
/-! ## SARIF Document Structure Tests -/
150169

151170
#guard
171+
let files := makeFilesMap "/test/file.st"
152172
let vcResults : VCResults := #[]
153-
let sarif := vcResultsToSarif vcResults
173+
let sarif := vcResultsToSarif files vcResults
154174
sarif.version = "2.1.0" &&
155175
sarif.runs.size = 1 &&
156176
match sarif.runs[0]? with
@@ -161,12 +181,15 @@ def makeVCResult (label : String) (outcome : Outcome) (smtResult : Result := .un
161181
#guard
162182
let md1 := makeMetadata "/test/file1.st" 10 5
163183
let md2 := makeMetadata "/test/file2.st" 20 10
184+
let files1 := makeFilesMap "/test/file1.st"
185+
let files2 := makeFilesMap "/test/file2.st"
186+
let files := files1.union files2
164187
let vcResults : VCResults := #[
165188
makeVCResult "obligation1" .pass .unsat md1,
166189
makeVCResult "obligation2" .fail (.sat []) md2,
167190
makeVCResult "obligation3" .unknown
168191
]
169-
let sarif := vcResultsToSarif vcResults
192+
let sarif := vcResultsToSarif files vcResults
170193
sarif.version = "2.1.0" &&
171194
sarif.runs.size = 1 &&
172195
match sarif.runs[0]? with
@@ -193,21 +216,23 @@ def makeVCResult (label : String) (outcome : Outcome) (smtResult : Result := .un
193216
-- Test full SARIF document JSON generation
194217
#guard
195218
let md := makeMetadata "/test/example.st" 15 7
219+
let files := makeFilesMap "/test/example.st"
196220
let vcResults : VCResults := #[
197221
makeVCResult "test_assertion" .pass .unsat md
198222
]
199-
let sarif := vcResultsToSarif vcResults
223+
let sarif := vcResultsToSarif files vcResults
200224
let jsonStr := Strata.Sarif.toJsonString sarif
201225
(jsonStr.splitOn "\"version\":\"2.1.0\"").length > 1 &&
202226
(jsonStr.splitOn "\"Strata\"").length > 1 &&
203227
(jsonStr.splitOn "test_assertion").length > 1
204228

205229
-- Test pretty JSON generation
206230
#guard
231+
let files := makeFilesMap "/test/file.st"
207232
let vcResults : VCResults := #[
208233
makeVCResult "simple_test" .pass
209234
]
210-
let sarif := vcResultsToSarif vcResults
235+
let sarif := vcResultsToSarif files vcResults
211236
let prettyJson := Strata.Sarif.toPrettyJsonString sarif
212237
prettyJson.contains '\n'
213238

@@ -217,68 +242,75 @@ def makeVCResult (label : String) (outcome : Outcome) (smtResult : Result := .un
217242
#guard
218243
let cex : SMTModel := [(({ name := "x", metadata := Visibility.unres }, some .int), "42")]
219244
let md := makeMetadata "/test/cex.st" 25 3
245+
let files := makeFilesMap "/test/cex.st"
220246
let vcr := makeVCResult "cex_obligation" .fail (.sat cex) md
221-
let sarifResult := vcResultToSarifResult vcr
247+
let sarifResult := vcResultToSarifResult files vcr
222248
sarifResult.level = Level.error &&
223249
(sarifResult.message.text.splitOn "counterexample").length > 1 &&
224250
sarifResult.locations.size = 1 &&
225251
match sarifResult.locations[0]? with
226252
| some loc =>
227253
loc.physicalLocation.artifactLocation.uri = "/test/cex.st" &&
228-
loc.physicalLocation.region.startLine = 25 &&
229-
loc.physicalLocation.region.startColumn = 3
254+
loc.physicalLocation.region.startLine = 1 &&
255+
loc.physicalLocation.region.startColumn = 0
230256
| none => false
231257

232258
/-! ## JSON Output Tests -/
233259

234260
/-- info: "{\"runs\":[{\"results\":[],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
235261
#guard_msgs in
236262
#eval
263+
let files := makeFilesMap "/test/file.st"
237264
let vcResults : VCResults := #[]
238-
let sarif := vcResultsToSarif vcResults
265+
let sarif := vcResultsToSarif files vcResults
239266
Strata.Sarif.toJsonString sarif
240267

241-
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"none\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/pass.st\"},\"region\":{\"startColumn\":5,\"startLine\":10}}}],\"message\":{\"text\":\"Verification succeeded\"},\"ruleId\":\"test_pass\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
268+
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"none\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/pass.st\"},\"region\":{\"startColumn\":0,\"startLine\":1}}}],\"message\":{\"text\":\"Verification succeeded\"},\"ruleId\":\"test_pass\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
242269
#guard_msgs in
243270
#eval
244271
let md := makeMetadata "/test/pass.st" 10 5
272+
let files := makeFilesMap "/test/pass.st"
245273
let vcResults : VCResults := #[makeVCResult "test_pass" .pass .unsat md]
246-
let sarif := vcResultsToSarif vcResults
274+
let sarif := vcResultsToSarif files vcResults
247275
Strata.Sarif.toJsonString sarif
248276

249-
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"error\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/fail.st\"},\"region\":{\"startColumn\":15,\"startLine\":20}}}],\"message\":{\"text\":\"Verification failed\"},\"ruleId\":\"test_fail\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
277+
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"error\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/fail.st\"},\"region\":{\"startColumn\":0,\"startLine\":1}}}],\"message\":{\"text\":\"Verification failed\"},\"ruleId\":\"test_fail\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
250278
#guard_msgs in
251279
#eval
252280
let md := makeMetadata "/test/fail.st" 20 15
281+
let files := makeFilesMap "/test/fail.st"
253282
let vcResults : VCResults := #[makeVCResult "test_fail" .fail (.sat []) md]
254-
let sarif := vcResultsToSarif vcResults
283+
let sarif := vcResultsToSarif files vcResults
255284
Strata.Sarif.toJsonString sarif
256285

257286
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"warning\",\"locations\":[],\"message\":{\"text\":\"Verification result unknown (solver timeout or incomplete)\"},\"ruleId\":\"test_unknown\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
258287
#guard_msgs in
259288
#eval
289+
let files := makeFilesMap "/test/file.st"
260290
let vcResults : VCResults := #[makeVCResult "test_unknown" .unknown]
261-
let sarif := vcResultsToSarif vcResults
291+
let sarif := vcResultsToSarif files vcResults
262292
Strata.Sarif.toJsonString sarif
263293

264294
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"error\",\"locations\":[],\"message\":{\"text\":\"Verification error: timeout\"},\"ruleId\":\"test_error\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
265295
#guard_msgs in
266296
#eval
297+
let files := makeFilesMap "/test/file.st"
267298
let vcResults : VCResults := #[makeVCResult "test_error" (.implementationError "timeout")]
268-
let sarif := vcResultsToSarif vcResults
299+
let sarif := vcResultsToSarif files vcResults
269300
Strata.Sarif.toJsonString sarif
270301

271-
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"none\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/multi.st\"},\"region\":{\"startColumn\":1,\"startLine\":5}}}],\"message\":{\"text\":\"Verification succeeded\"},\"ruleId\":\"obligation1\"},{\"level\":\"error\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/multi.st\"},\"region\":{\"startColumn\":1,\"startLine\":10}}}],\"message\":{\"text\":\"Verification failed\"},\"ruleId\":\"obligation2\"},{\"level\":\"warning\",\"locations\":[],\"message\":{\"text\":\"Verification result unknown (solver timeout or incomplete)\"},\"ruleId\":\"obligation3\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
302+
/-- info: "{\"runs\":[{\"results\":[{\"level\":\"none\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/multi.st\"},\"region\":{\"startColumn\":0,\"startLine\":1}}}],\"message\":{\"text\":\"Verification succeeded\"},\"ruleId\":\"obligation1\"},{\"level\":\"error\",\"locations\":[{\"physicalLocation\":{\"artifactLocation\":{\"uri\":\"/test/multi.st\"},\"region\":{\"startColumn\":0,\"startLine\":1}}}],\"message\":{\"text\":\"Verification failed\"},\"ruleId\":\"obligation2\"},{\"level\":\"warning\",\"locations\":[],\"message\":{\"text\":\"Verification result unknown (solver timeout or incomplete)\"},\"ruleId\":\"obligation3\"}],\"tool\":{\"driver\":{\"informationUri\":\"https://github.com/strata-org/Strata\",\"name\":\"Strata\",\"version\":\"0.1.0\"}}}],\"schema\":\"https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json\",\"version\":\"2.1.0\"}" -/
272303
#guard_msgs in
273304
#eval
274305
let md1 := makeMetadata "/test/multi.st" 5 1
275306
let md2 := makeMetadata "/test/multi.st" 10 1
307+
let files := makeFilesMap "/test/multi.st"
276308
let vcResults : VCResults := #[
277309
makeVCResult "obligation1" .pass .unsat md1,
278310
makeVCResult "obligation2" .fail (.sat []) md2,
279311
makeVCResult "obligation3" .unknown
280312
]
281-
let sarif := vcResultsToSarif vcResults
313+
let sarif := vcResultsToSarif files vcResults
282314
Strata.Sarif.toJsonString sarif
283315

284316
end Core.Sarif.Tests

StrataVerify.lean

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,10 @@ def main (args : List String) : IO UInt32 := do
117117
if file.endsWith ".csimp.st" then
118118
println! "SARIF output is not supported for C_Simp files (.csimp.st) because location metadata is not preserved during translation to Core."
119119
else
120-
let sarifDoc := Core.Sarif.vcResultsToSarif vcResults
120+
-- Create a files map with the single input file
121+
let uri := Strata.Uri.file file
122+
let files := Map.empty.insert uri inputCtx.fileMap
123+
let sarifDoc := Core.Sarif.vcResultsToSarif files vcResults
121124
let sarifJson := Strata.Sarif.toPrettyJsonString sarifDoc
122125
let sarifFile := file ++ ".sarif"
123126
try

0 commit comments

Comments
 (0)