Skip to content

Commit 1a08f87

Browse files
committed
Merge branch 'main' into lhk_dev
2 parents 1def7ab + 8358601 commit 1a08f87

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+30187
-1
lines changed

cli/query/run.py

+189
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import logging
3+
import os.path
34
import re
45
import shutil
56
import 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+
278463
def 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:

cli/sparrow

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22

33
# A convenient method to return the actual path even for non symlinks
44
# and multi-level symlinks.

cli/sparrow-cli.py

+8
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,14 @@ def parse_args():
7676
subparser_query_run.add_argument("--gdl", '-gdl', required=True, nargs="*", dest="godel_dir",
7777
help='The location of the godel script that needs to execute')
7878
subparser_query_run.add_argument('--verbose', action='store_true', help='Enable verbose mode')
79+
subparser_query_run.add_argument('--sarif', action='store_true', help='Turn on the sarif report option, all '
80+
'outputs will be merged into one sarif, '
81+
'and the output result will be '
82+
'sparrow-cli-report.sarif in the output '
83+
'directory. The original godel script '
84+
'output must contain information such as '
85+
'filePath, startLine, ruleName, '
86+
'ruleDescription, etc.')
7987
subparser_query_run.add_argument('--merge', '-m', action='store_true', help='Combined execution of multiple '
8088
'scripts,Only one function and class '
8189
'with the same name in the script '

0 commit comments

Comments
 (0)