11import json
22import logging
3+ import os .path
34import re
45import shutil
56import sqlite3
@@ -275,6 +276,190 @@ def merge_execute(args, gdl_list, timeout):
275276 f .write (json .dumps (content , indent = 4 ))
276277
277278
279+ def json_to_sarif (sarif_data , json_data ):
280+ rules_dict = dict ()
281+ for bug in json_data :
282+ # ruleName
283+ if "ruleName" in bug :
284+ rule_id = bug .get ("ruleName" )
285+ else :
286+ return False
287+ # filePath
288+ if "filePath" in bug :
289+ file_path = bug .get ("filePath" )
290+ else :
291+ return False
292+ # startLine
293+ if "startLine" in bug :
294+ start_line = bug .get ("startLine" )
295+ else :
296+ return False
297+ # ruleDescription
298+ if "ruleDescription" in bug :
299+ rule_description = bug .get ("ruleDescription" )
300+ else :
301+ return False
302+ # bug message
303+ if "message" in bug :
304+ message = bug .get ("message" )
305+ else :
306+ message = rule_description
307+ level = "error"
308+ if "level" in bug :
309+ level = bug .get ("level" ).lower ()
310+ if rule_id not in rules_dict :
311+ rule_index = len (rules_dict )
312+ rules_dict [rule_id ] = rule_index
313+ res = {
314+ "id" : rule_id ,
315+ "name" : rule_id ,
316+ "shortDescription" : {
317+ "text" : rule_description
318+ },
319+ "fullDescription" : {
320+ "text" : rule_description
321+ },
322+ "defaultConfiguration" : {
323+ "level" : level
324+ }
325+ }
326+ sarif_data ["runs" ][0 ]["tool" ]["driver" ]["rules" ].append (res )
327+ else :
328+ rule_index = rules_dict [rule_id ]
329+ thread_flow_locations = []
330+ thread_flow_locations .append ({
331+ "location" : {
332+ "physicalLocation" : {
333+ "artifactLocation" : {
334+ "uri" : file_path
335+ },
336+ "region" : {
337+ "startLine" : start_line ,
338+ "endLine" : start_line ,
339+ "snippet" : {
340+ "text" : ""
341+ }
342+ },
343+ "contextRegion" : {
344+ "startLine" : start_line ,
345+ "endLine" : start_line ,
346+ "snippet" : {
347+ "text" : ""
348+ }
349+ }
350+ },
351+ "message" : {
352+ "text" : message
353+ }
354+ }
355+ })
356+ sarif_data ["runs" ][0 ]["results" ].append ({
357+ "ruleId" : rule_id ,
358+ "ruleIndex" : rule_index ,
359+ "level" : "error" if bug .get ("Importance" , "" ).lower () == "high" else "warning" ,
360+ "message" : {
361+ "text" : message
362+ },
363+ "locations" : [
364+ {
365+ "physicalLocation" : {
366+ "artifactLocation" : {
367+ "uri" : thread_flow_locations [0 ]["location" ]["physicalLocation" ]["artifactLocation" ][
368+ "uri" ]
369+ },
370+ "region" : {
371+ "startLine" : thread_flow_locations [0 ]["location" ]["physicalLocation" ]["region" ][
372+ "startLine" ],
373+ "endLine" : thread_flow_locations [0 ]["location" ]["physicalLocation" ]["region" ][
374+ "startLine" ],
375+ "snippet" : {
376+ "text" : ""
377+ }
378+ },
379+ "contextRegion" : {
380+ "startLine" : thread_flow_locations [0 ]["location" ]["physicalLocation" ]["region" ][
381+ "startLine" ],
382+ "endLine" : thread_flow_locations [0 ]["location" ]["physicalLocation" ]["region" ][
383+ "startLine" ],
384+ "snippet" : {
385+ "text" : ""
386+ }
387+ }
388+ },
389+ "message" : {
390+ "text" : message
391+ },
392+ }
393+ ],
394+ "codeFlows" : [
395+ {
396+ "threadFlows" : [
397+ {
398+ "locations" : thread_flow_locations
399+ }
400+ ]
401+ }
402+ ]
403+ })
404+ return True
405+
406+
407+ def output_to_sarif (args ):
408+ # 脚本收集
409+ godel_path_list = list ()
410+ for godel_dir in args .godel_dir :
411+ godel_path_list += get_files (godel_dir , ".gdl" )
412+ godel_path_list += get_files (godel_dir , ".gs" )
413+ sarif_data = {
414+ "version" : "2.1.0" ,
415+ "$schema" : "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json" ,
416+ "runs" : [
417+ {
418+ "tool" : {
419+ "driver" : {
420+ "name" : "Custom Tool" ,
421+ "informationUri" : "https://example.com" ,
422+ "rules" : []
423+ }
424+ },
425+ "results" : []
426+ }
427+ ]
428+ }
429+ # 获取脚本对应的结果并写入sarif报告中
430+ for godel_query_script in godel_path_list :
431+ output = str (Path (args .output ).expanduser ().resolve () / (godel_query_script .stem + "." + args .format ))
432+ if not os .path .exists (output ):
433+ logging .warning ("%s does not exist, it seems that there is a problem with the %s, please check the script" ,
434+ output , str (godel_query_script ))
435+ continue
436+ with open (output , "r" ) as f :
437+ output_json = json .load (f )
438+ # 脚本单输出直接转
439+ if isinstance (output_json , list ):
440+ status = json_to_sarif (sarif_data , output_json )
441+ if not status :
442+ logging .warning ("The output of %s needs to include filePath, startLine, ruleName,ruleDescription. it "
443+ "can not trans to sarif" , godel_query_script )
444+ else :
445+ logging .info ("%s trans to sarif success" , godel_query_script )
446+ # 脚本多输出分别转过去
447+ else :
448+ trans = True
449+ for key , value in output_json .items ():
450+ status = json_to_sarif (sarif_data , value )
451+ if not status :
452+ logging .warning ("The output of %s %s needs to include filePath, startLine, "
453+ "ruleName,ruleDescription. it can not trans to sarif" , godel_query_script , key )
454+ trans = False
455+ if trans :
456+ logging .info ("%s trans to sarif success" , godel_query_script )
457+
458+ output = str (Path (args .output ).expanduser ().resolve () / ("sparrow-cli-report.sarif" ))
459+ with open (output , "w" ) as f :
460+ f .write (json .dumps (sarif_data , indent = 4 ))
461+
462+
278463def query_run (args ):
279464 # conf 检查
280465 if not conf_check (args ):
@@ -295,6 +480,8 @@ def query_run(args):
295480 logging .warning ("When merging execution, please make sure that single reservation of functions or classes "
296481 "with the same name will not affect the execution results." )
297482 merge_execute (args , godel_path_list , args .timeout )
483+ if args .sarif :
484+ output_to_sarif (args )
298485 return
299486 status = 1
300487 # 目前先各自执行:
@@ -317,6 +504,8 @@ def query_run(args):
317504 logging .error ("Task %s is %s, result is %s, execution time is %.2fs." ,
318505 str (godel_query_script ), "fail" , "null" , time .time () - start_time )
319506 logging .error ("%s execute error, please check by log" , str (godel_query_script ))
507+ if args .sarif :
508+ output_to_sarif (args )
320509 if status == 1 :
321510 logging .info ("run success" )
322511 else :
0 commit comments