Skip to content

Commit 43e8ffe

Browse files
authored
Merge pull request diffblue#50 from diffblue/marek/update_of_python_driver_PR
Marek/update of python driver of the whole analyser.
2 parents bdf6a77 + 97256ba commit 43e8ffe

File tree

5 files changed

+768
-301
lines changed

5 files changed

+768
-301
lines changed

security-scanner/analyser.py

Lines changed: 139 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
import os
22
import time
33
import json
4+
import shutil
45

56

67
def __get_my_dir(): return os.path.dirname(os.path.realpath(__file__))
78

89

9-
def get_possible_analyser_binary_pathnames():
10-
result = []
11-
for rdir in ["./", "../src/driver"]:
12-
fname = os.path.abspath(os.path.join(__get_my_dir(), rdir, "security-analyzer"))
13-
result.append(fname)
14-
return result
10+
def get_security_analyser_pathname():
11+
return os.path.abspath(os.path.join(__get_my_dir(), "../src/driver/security-analyzer"))
1512

13+
def get_goto_instrument_pathname():
14+
return os.path.abspath(os.path.join(__get_my_dir(), "../cbmc/src/goto-instrument/goto-instrument"))
1615

17-
def get_analyser_binary_pathname():
18-
for fname in get_possible_analyser_binary_pathnames():
19-
if os.path.exists(fname) and os.path.isfile(fname):
20-
return fname
21-
return None
16+
def get_cbmc_pathname():
17+
return os.path.abspath(os.path.join(__get_my_dir(), "../cbmc/src/cbmc/cbmc"))
2218

19+
def get_symex_pathname():
20+
return os.path.abspath(os.path.join(__get_my_dir(), "../cbmc/src/symex/symex"))
2321

24-
def run_analyser(
22+
23+
def run_security_analyser(
2524
root_jar,
2625
transition_rules_file_pathname,
2726
timeout,
@@ -33,23 +32,23 @@ def run_analyser(
3332
results_dir,
3433
temp_root_dir
3534
):
36-
prof = { "duration": time.time() }
35+
prof = {}
36+
prof_start_time = time.time()
37+
3738
if not os.path.exists(results_dir):
3839
os.makedirs(results_dir)
3940

4041
# Building the program JSON file (the list of all JARs application consists of) for the security analyser
4142
program_json_fname = os.path.abspath(os.path.join(results_dir, "program.json"))
4243
print("Building the program JSON file (the list of all JARs application consists of) for the 'goto-analyser': "
4344
+ program_json_fname)
44-
program_json_file = open(program_json_fname,"w")
45-
program_jars_list = [ os.path.relpath(root_jar,results_dir) ]
46-
program_json_file.write(json.dumps(program_jars_list,sort_keys=True,indent=4))
47-
program_json_file.close()
45+
with open(program_json_fname,"w") as program_json_file:
46+
program_jars_list = [ os.path.relpath(root_jar,results_dir) ]
47+
program_json_file.write(json.dumps(program_jars_list,sort_keys=True,indent=4))
4848

4949
# Building the root config file for the security analyser
5050
root_config_json_fname = os.path.abspath(os.path.join(results_dir, "config.json"))
5151
print("Building the root config JSON file for 'goto-analyser': " + root_config_json_fname)
52-
root_config_json_file = open(root_config_json_fname,"w")
5352
root_config_json = {
5453
"program": "./program.json",
5554
"rules": os.path.relpath(transition_rules_file_pathname,results_dir),
@@ -77,27 +76,142 @@ def run_analyser(
7776
root_config_json["dump_html_program"] = True
7877
else:
7978
root_config_json["dump_html_program"] = False
80-
root_config_json_file.write(json.dumps(root_config_json,sort_keys=True,indent=4))
81-
root_config_json_file.close()
79+
with open(root_config_json_fname, "w") as root_config_json_file:
80+
root_config_json_file.write(json.dumps(root_config_json, sort_keys=True, indent=4))
8281

8382
if not os.path.exists(results_dir):
8483
os.makedirs(results_dir)
8584

8685
old_cwd = os.getcwd()
8786
os.chdir(results_dir)
8887
command = (
89-
get_analyser_binary_pathname() + " "
88+
get_security_analyser_pathname() + " "
9089
+ "'./" + os.path.relpath(root_jar,results_dir) + "' "
9190
"--security-scanner '" + os.path.relpath(root_config_json_fname,results_dir) + "' "
9291
)
93-
prof["calling_goto_analyser"] = { "duration": time.time() }
94-
print("Invoking 'security_analyser' ...")
92+
prof["calling_goto_analyser"] = {}
93+
prof_calling_goto_analyser_start_time = time.time()
94+
print("Invoking 'security-analyser' ...")
9595
if verbosity >= 9:
9696
print("CWD: " + results_dir)
9797
print("CMD: " + command)
9898
os.system(command)
99-
prof["calling_goto_analyser"]["duration"] = time.time() - prof["calling_goto_analyser"]["duration"]
99+
prof["calling_goto_analyser"]["duration"] = time.time() - prof_calling_goto_analyser_start_time
100100
os.chdir(old_cwd)
101-
prof["duration"] = time.time() - prof["duration"]
101+
prof["duration"] = time.time() - prof_start_time
102+
103+
return prof
104+
105+
106+
def run_program_slicing(
107+
json_cfg_fname,
108+
results_dir,
109+
timeout,
110+
verbosity
111+
):
112+
prof = {}
113+
prof_start_time = time.time()
102114

115+
# TODO: once the slicer in "goto-instrument" tool is available, then provide proper implementation here!
116+
# Until then we assume the slicing removes nothing from the instrumented program.
117+
shutil.copyfile(json_cfg_fname, os.path.join(os.path.dirname(json_cfg_fname),"sliced_goto_programs.json"))
118+
119+
prof["duration"] = time.time() - prof_start_time
103120
return prof
121+
122+
123+
def append_cbmc_error_trace_if_it_is_relevant(trace, trace_id, results_dir, cfg, traces_list):
124+
"""A trace is relevant, if it ends at a sink."""
125+
was_trace_saved = False
126+
last_rec = trace[-1]
127+
if "sourceLocation" in last_rec:
128+
loc = last_rec["sourceLocation"]
129+
for sink in cfg["sinks"]:
130+
if loc["file"] == sink["file"] and \
131+
loc["function"] == sink["function"] and \
132+
loc["line"] == str(sink["line"]):
133+
trace_fname = os.path.join(results_dir, "error_trace_" + str(trace_id) + ".json")
134+
with open(trace_fname, "w") as trace_file:
135+
trace_file.write(json.dumps(trace, sort_keys=False, indent=4))
136+
was_trace_saved = True
137+
138+
found = False
139+
for rec in traces_list:
140+
if rec["file"] == sink["file"] and \
141+
rec["function"] == sink["function"] and \
142+
rec["line"] == sink["line"] and \
143+
rec["goto_binary_file"] == cfg["goto_binary_file"]:
144+
rec["error_traces"].append(trace_fname)
145+
if found == False:
146+
rec = sink
147+
rec["goto_binary_file"] = cfg["goto_binary_file"]
148+
rec["error_traces"] = [trace_fname]
149+
traces_list.append(rec)
150+
break
151+
return was_trace_saved
152+
153+
154+
def run_search_for_error_traces(
155+
json_cfg_fname,
156+
results_dir,
157+
timeout,
158+
verbosity
159+
):
160+
prof = {}
161+
prof_start_time = time.time()
162+
if not os.path.exists(results_dir):
163+
os.makedirs(results_dir)
164+
165+
trace_id = 0
166+
traces_list = []
167+
168+
with open(json_cfg_fname) as data_file:
169+
cfgs = json.load(data_file)
170+
for cfg in cfgs:
171+
old_cwd = os.getcwd()
172+
os.chdir(results_dir)
173+
command = (
174+
get_cbmc_pathname() + " " +
175+
cfg["goto_binary_file"] + " " +
176+
" --trace --lazy-methods --json-ui --unwind 10 " +
177+
"--verbosity " + str(1) + " "
178+
"> \"cbmc_results.json\""
179+
)
180+
prof["calling_cbmc"] = {}
181+
prof_calling_cbmc_start_time = time.time()
182+
print("Invoking 'cbmc' ...")
183+
if verbosity >= 9:
184+
print("CWD: " + results_dir)
185+
print("CMD: " + command)
186+
os.system(command)
187+
prof["calling_cbmc"]["duration"] = time.time() - prof_calling_cbmc_start_time
188+
os.chdir(old_cwd)
189+
190+
with open(os.path.join(results_dir,"cbmc_results.json")) as data_file:
191+
cbmc_results = json.load(data_file)
192+
for outer_element in cbmc_results:
193+
if "result" in outer_element:
194+
for inner_element in outer_element["result"]:
195+
if "trace" in inner_element and len(inner_element["trace"]) > 0:
196+
trace=inner_element["trace"]
197+
was_trace_saved = append_cbmc_error_trace_if_it_is_relevant(
198+
trace,
199+
trace_id,
200+
results_dir,
201+
cfg,
202+
traces_list
203+
)
204+
if was_trace_saved:
205+
trace_id += 1
206+
207+
with open(os.path.join(results_dir, "error_traces.json"), "w") as traces_file:
208+
traces_file.write(json.dumps(traces_list, sort_keys=True, indent=4))
209+
210+
prof["duration"] = time.time() - prof_start_time
211+
return prof
212+
213+
214+
215+
216+
if __name__ == "__main__":
217+
pass

security-scanner/mkbench.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,18 @@ def __get_my_dir(): return os.path.dirname(os.path.realpath(__file__))
99

1010

1111
def collect_java_files(app_build_dir,extension_text,output_list):
12-
prof = { "duration": time.time() }
12+
prof = {}
13+
prof_start_time = time.time()
1314
for root, dirnames, filenames in os.walk(app_build_dir):
1415
for filename in fnmatch.filter(filenames, "*." + extension_text):
1516
output_list.append(os.path.abspath(os.path.join(root,filename)))
16-
prof["duration"] = time.time() - prof["duration"]
17+
prof["duration"] = time.time() - prof_start_time
1718
return prof
1819

1920

2021
def unpack_java_package(pathname,unpack_dir):
21-
prof = { "duration": time.time() }
22+
prof = {}
23+
prof_start_time = time.time()
2224
if not os.path.exists(unpack_dir):
2325
os.makedirs(unpack_dir)
2426
old_cwd = os.getcwd()
@@ -29,12 +31,13 @@ def unpack_java_package(pathname,unpack_dir):
2931
pathname
3032
)
3133
os.chdir(old_cwd)
32-
prof["duration"] = time.time() - prof["duration"]
34+
prof["duration"] = time.time() - prof_start_time
3335
return prof
3436

3537

3638
def pack_classes_to_jar(classes_dir,dst_file):
37-
prof = { "duration": time.time() }
39+
prof = {}
40+
prof_start_time = time.time()
3841
if not os.path.exists(os.path.dirname(dst_file)):
3942
os.makedirs(os.path.dirname(dst_file))
4043
old_cwd = os.getcwd()
@@ -44,7 +47,7 @@ def pack_classes_to_jar(classes_dir,dst_file):
4447
+ dst_file + "\" ."
4548
)
4649
os.chdir(old_cwd)
47-
prof["duration"] = time.time() - prof["duration"]
50+
prof["duration"] = time.time() - prof_start_time
4851
return prof
4952

5053

@@ -100,11 +103,13 @@ def is_class_modeled(pathname):
100103

101104

102105
def install_class_file(pathname,output_dir,class_temp_dir):
103-
prof = { "duration": time.time() }
106+
prof = {}
107+
prof_start_time = time.time()
104108
print(" " + pathname)
105-
prof["fullname"] = { "duration": time.time() }
109+
prof["fullname"] = {}
110+
prof_fullname_start_time = time.time()
106111
packages_classname = compute_fullname_of_class(pathname,class_temp_dir)
107-
prof["fullname"]["duration"] = time.time() - prof["fullname"]["duration"]
112+
prof["fullname"]["duration"] = time.time() - prof_fullname_start_time
108113
if packages_classname is None:
109114
print("FAIL: Cannot read full class name (including packages) of the class file: " + pathname)
110115
prof["duration"] = time.time() - prof["duration"]
@@ -120,12 +125,13 @@ def install_class_file(pathname,output_dir,class_temp_dir):
120125
else:
121126
shutil.copyfile(pathname,class_pathname)
122127

123-
prof["duration"] = time.time() - prof["duration"]
128+
prof["duration"] = time.time() - prof_start_time
124129
return prof
125130

126131

127132
def install_jar_file(pathname,output_dir,temp_dir,class_temp_dir):
128-
prof = { "duration": time.time() }
133+
prof = {}
134+
prof_start_time = time.time()
129135

130136
prof["unpack"] = unpack_java_package(pathname,temp_dir)
131137

@@ -140,12 +146,13 @@ def install_jar_file(pathname,output_dir,temp_dir,class_temp_dir):
140146
prof["install"]["duration"] += prof_install["duration"]
141147
prof["install"]["fullname"]["duration"] += prof_install["fullname"]["duration"]
142148

143-
prof["duration"] = time.time() - prof["duration"]
149+
prof["duration"] = time.time() - prof_start_time
144150
return prof
145151

146152

147153
def install_war_file(pathname,output_dir,temp_dir,class_temp_dir):
148-
prof = { "duration": time.time() }
154+
prof = {}
155+
prof_start_time = time.time()
149156

150157
war_temp_dir = os.path.join(temp_dir,"WAR")
151158
prof["unpack"] = unpack_java_package(pathname,war_temp_dir)
@@ -176,12 +183,13 @@ def install_war_file(pathname,output_dir,temp_dir,class_temp_dir):
176183
prof["install"]["duration"] += prof_install["install"]["duration"]
177184
prof["install"]["fullname"]["duration"] += prof_install["install"]["fullname"]["duration"]
178185

179-
prof["duration"] = time.time() - prof["duration"]
186+
prof["duration"] = time.time() - prof_start_time
180187
return prof
181188

182189

183190
def build_classes_configuration(app_binary_dir,output_dir,temp_dir):
184-
prof = { "duration": time.time() }
191+
prof = {}
192+
prof_start_time = time.time()
185193

186194
prof["unpack"] = {"duration": 0.0}
187195
prof["collect"] = {"duration": 0.0}
@@ -229,5 +237,5 @@ def build_classes_configuration(app_binary_dir,output_dir,temp_dir):
229237
prof["install"]["duration"] += prof_install["install"]["duration"]
230238
prof["install"]["fullname"]["duration"] += prof_install["install"]["fullname"]["duration"]
231239

232-
prof["duration"] = time.time() - prof["duration"]
240+
prof["duration"] = time.time() - prof_start_time
233241
return prof

0 commit comments

Comments
 (0)