1
1
import json
2
2
import logging
3
+ import os .path
3
4
import re
4
5
import shutil
5
6
import sqlite3
@@ -275,6 +276,190 @@ def merge_execute(args, gdl_list, timeout):
275
276
f .write (json .dumps (content , indent = 4 ))
276
277
277
278
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
+
278
463
def query_run (args ):
279
464
# conf 检查
280
465
if not conf_check (args ):
@@ -295,6 +480,8 @@ def query_run(args):
295
480
logging .warning ("When merging execution, please make sure that single reservation of functions or classes "
296
481
"with the same name will not affect the execution results." )
297
482
merge_execute (args , godel_path_list , args .timeout )
483
+ if args .sarif :
484
+ output_to_sarif (args )
298
485
return
299
486
status = 1
300
487
# 目前先各自执行:
@@ -317,6 +504,8 @@ def query_run(args):
317
504
logging .error ("Task %s is %s, result is %s, execution time is %.2fs." ,
318
505
str (godel_query_script ), "fail" , "null" , time .time () - start_time )
319
506
logging .error ("%s execute error, please check by log" , str (godel_query_script ))
507
+ if args .sarif :
508
+ output_to_sarif (args )
320
509
if status == 1 :
321
510
logging .info ("run success" )
322
511
else :
0 commit comments