Skip to content

Commit 7022b47

Browse files
committed
REP: add json output to chkx report patchcandidates
1 parent b0e1c0a commit 7022b47

File tree

2 files changed

+106
-52
lines changed

2 files changed

+106
-52
lines changed

chb/buffer/LibraryCallCallsites.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,49 @@ def lentype(self) -> str:
227227
else:
228228
return lenterm
229229

230+
@property
231+
def dstoffset(self) -> Optional[int]:
232+
"""Returns the stack offset for our destination buffer"""
233+
if self.dstarg is None:
234+
return None
235+
return self.dstarg.stack_address_offset()
236+
237+
def to_json_result(self) -> JSONResult:
238+
if self.dstarg is None:
239+
chklogger.logger.warning(
240+
"No expression found for destination argument: %s", self)
241+
return JSONResult("librarycallsideeffect", {}, "fail",
242+
"No expression found for destination argument")
243+
dstoffset = self.dstoffset
244+
if dstoffset is None:
245+
chklogger.logger.warning(
246+
"No value found for destination stack offset : %s", self)
247+
return JSONResult("librarycallsideeffect", {}, "fail",
248+
"No value found for destination stack offset")
249+
250+
fn = self.instr.function
251+
stackframe = fn.stackframe
252+
stackbuffer = stackframe.get_stack_buffer(dstoffset)
253+
if stackbuffer is None:
254+
chklogger.logger.warning(
255+
"No stackbuffer found for %s at offset %s", self.instr, dstoffset)
256+
return JSONResult("librarycallsideeffect", {}, "fail",
257+
"No stackbuffer found for %s at offset %s" %
258+
(self.instr, dstoffset))
259+
260+
buffersize = stackbuffer.size
261+
262+
content: Dict[str, Any] = {}
263+
content["annotation"] = self.instr.annotation
264+
content["faddr"] = self.faddr
265+
content["iaddr"] = self.instr.iaddr
266+
content["buffersize"] = buffersize
267+
content["target-function"] = self.summary.name
268+
content["stack-offset"] = dstoffset
269+
content["length-argument"] = str(self.lenarg)
270+
271+
return JSONResult("librarycallsideeffect", content, "ok")
272+
230273
def __str__(self) -> str:
231274
return self.instr.iaddr + ": " + str(self.instr.annotation)
232275

chb/cmdline/reportcmds.py

Lines changed: 63 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,30 @@ def perc(v: float) -> str:
989989
exit(0)
990990

991991

992+
def write_json_result(xfilename: Optional[str],
993+
jresult: JSONResult,
994+
schema_name: str,
995+
) -> None:
996+
if jresult.is_ok:
997+
okresult = JU.jsonok(schema_name, jresult.content)
998+
if xfilename is not None:
999+
filename = xfilename + ".json"
1000+
with open(filename, "w") as fp:
1001+
json.dump(okresult, fp, indent=2)
1002+
chklogger.logger.info("JSON output written to " + filename)
1003+
else:
1004+
print(json.dumps(okresult))
1005+
else:
1006+
failresult = JU.jsonfail(jresult.reason)
1007+
if xfilename is not None:
1008+
filename = xfilename + ".json"
1009+
with open(filename, "w") as fp:
1010+
json.dump(failresult, fp, indent=2)
1011+
chklogger.logger.warning(
1012+
"JSON failure output written to " + filename)
1013+
else:
1014+
print(json.dumps(failresult))
1015+
9921016
def report_buffer_bounds(args: argparse.Namespace) -> NoReturn:
9931017

9941018
# arguments
@@ -1022,49 +1046,27 @@ def report_buffer_bounds(args: argparse.Namespace) -> NoReturn:
10221046
if calltgt.is_so_target:
10231047
libcalls.add_library_callsite(faddr, instr)
10241048

1025-
def write_json_result(
1026-
xfilename: Optional[str], jresult: JSONResult) -> None:
1027-
if jresult.is_ok:
1028-
okresult = JU.jsonok("bufferboundsassessment", jresult.content)
1029-
if xfilename is not None:
1030-
filename = xfilename + ".json"
1031-
with open(filename, "w") as fp:
1032-
json.dump(okresult, fp, indent=2)
1033-
chklogger.logger.info("JSON output written to " + filename)
1034-
else:
1035-
print(json.dumps(okresult))
1036-
else:
1037-
failresult = JU.jsonfail(jresult.reason)
1038-
if xfilename is not None:
1039-
filename = xfilename + ".json"
1040-
with open(filename, "w") as fp:
1041-
json.dump(failresult, fp, indent=2)
1042-
chklogger.logger.warning(
1043-
"JSON failure output written to " + filename)
1044-
else:
1045-
print(json.dumps(failresult))
1046-
10471049
if xjson:
10481050
content: Dict[str, Any] = {}
10491051
xinfodata = xinfo.to_json_result()
10501052
if xinfodata.is_ok:
10511053
content["identification"] = xinfodata.content
10521054
else:
1053-
write_json_result(xoutput, xinfodata)
1055+
write_json_result(xoutput, xinfodata, "bufferboundsassessment")
10541056
analysisstats = app.result_metrics.to_json_result()
10551057
if analysisstats.is_ok:
10561058
content["analysis"] = analysisstats.content
10571059
else:
1058-
write_json_result(xoutput, analysisstats)
1060+
write_json_result(xoutput, analysisstats, "bufferboundsassessment")
10591061

10601062
libcallsresult = libcalls.to_json_result()
10611063
if libcallsresult.is_ok:
10621064
content["bounds"] = libcallsresult.content
10631065
else:
1064-
write_json_result(xoutput, libcallsresult)
1066+
write_json_result(xoutput, libcallsresult,"bufferboundsassessment" )
10651067

10661068
write_json_result(xoutput, JSONResult(
1067-
"libcboundsanalysis", content, "ok"))
1069+
"libcboundsanalysis", content, "ok"), "bufferboundsassessment")
10681070

10691071
if not xverbose:
10701072
exit(0)
@@ -1174,38 +1176,47 @@ def include_target(target: 'CallTarget') -> bool:
11741176
if calltgt.is_so_target and include_target(calltgt):
11751177
libcalls.add_library_callsite(faddr, instr)
11761178

1177-
print("Number of calls: " + str(n_calls))
1179+
chklogger.logger.debug("Number of calls: %s", n_calls)
11781180

11791181
patchcallsites = libcalls.patch_callsites()
11801182

1183+
content: Dict[str, Any] = {}
1184+
if xjson:
1185+
xinfodata = xinfo.to_json_result()
1186+
if xinfodata.is_ok:
1187+
content["identification"] = xinfodata.content
1188+
else:
1189+
write_json_result(xoutput, xinfodata, "patchcandidates")
1190+
1191+
patch_records = []
1192+
11811193
for pc in sorted(patchcallsites, key=lambda pc:pc.faddr):
1182-
instr = pc.instr
1183-
dstarg = pc.dstarg
1184-
if dstarg is None:
1185-
chklogger.logger.warning(
1186-
"No expression found for destination argument: %s",
1187-
str(instr))
1188-
continue
1189-
dstoffset = dstarg.stack_address_offset()
1190-
fn = instr.function
1191-
stackframe = fn.stackframe
1192-
stackbuffer = stackframe.get_stack_buffer(dstoffset)
1193-
if stackbuffer is None:
1194-
chklogger.logger.warning(
1195-
"No stackbuffer found for %s at offset %s",
1196-
str(instr), str(dstoffset))
1194+
jresult = pc.to_json_result()
1195+
if not jresult.is_ok:
1196+
chklogger.logger.warning("Couldn't process patch callsite %s", pc)
11971197
continue
1198-
buffersize = stackbuffer.size
1199-
1200-
print(" " + pc.instr.iaddr + " " + pc.instr.annotation)
1201-
print(" - faddr: " + pc.faddr)
1202-
print(" - iaddr: " + pc.instr.iaddr)
1203-
print(" - target function: " + str(pc.summary.name))
1204-
print(" - stack offset: " + str(dstoffset))
1205-
print(" - length argument: " + str(pc.lenarg))
1206-
print(" - buffersize: " + str(buffersize))
1198+
1199+
patch_records.append(jresult.content)
1200+
1201+
content["patch-records"] = patch_records
1202+
chklogger.logger.debug("Number of patch callsites: %s", len(content['patch-records']))
1203+
1204+
if xjson:
1205+
jcontent = JSONResult("patchcandidates", content, "ok")
1206+
write_json_result(xoutput, jcontent, "patchcandidates")
1207+
exit(0)
1208+
1209+
for patch_record in content["patch-records"]:
1210+
print(" " + patch_record['iaddr'] + " " + patch_record['annotation'])
1211+
print(" - faddr: %s" % patch_record['faddr'])
1212+
print(" - iaddr: %s" % patch_record['iaddr'])
1213+
print(" - target function: %s" % patch_record['target-function'])
1214+
print(" - stack offset: %s" % patch_record['stack-offset'])
1215+
print(" - length argument: %s" % patch_record['length-argument'])
1216+
print(" - buffersize: %s" % patch_record['buffersize'])
12071217
print("")
12081218

1209-
print("Number of patch callsites: " + str(len(patchcallsites)))
1219+
print("Generated %d patch records from %d library calls" %
1220+
(len(content['patch-records']), n_calls))
12101221

12111222
exit(0)

0 commit comments

Comments
 (0)