Skip to content

Commit b504454

Browse files
committed
Merge branch 'master' into globalmemorymap
2 parents 4bccce0 + cbedfd1 commit b504454

File tree

4 files changed

+131
-45
lines changed

4 files changed

+131
-45
lines changed

chb/arm/opcodes/ARMAdd.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,39 @@ def pointer_arithmetic_expr() -> AST.ASTExpr:
214214
hl_rhs1_type = hl_rhs1.ctype(astree.ctyper)
215215
hl_rhs2_type = hl_rhs2.ctype(astree.ctyper)
216216

217-
if hl_rhs1_type is None:
217+
if hl_rhs1_type is None and hl_rhs2_type is None:
218218
chklogger.logger.error(
219219
"Unable to lift pointer arithmetic without type for "
220220
+ "%s at address %s",
221221
str(rhs3), iaddr)
222222
return astree.mk_temp_lval_expression()
223223

224-
if hl_rhs1_type.is_pointer:
224+
if hl_rhs2_type is not None and hl_rhs2_type.is_pointer:
225+
rhs2tgttyp = cast(AST.ASTTypPtr, hl_rhs2_type).tgttyp
226+
tgttypsize = astree.type_size_in_bytes(rhs2tgttyp)
227+
if tgttypsize is None:
228+
chklogger.logger.warning(
229+
"Unable to lift pointer arithmetic without size for "
230+
+ "%s at address %s; set type size to 1",
231+
str(hl_rhs2_type), iaddr)
232+
# return astree.mk_temp_lval_expression()
233+
tgttypsize = 1
234+
235+
if tgttypsize == 1:
236+
return XU.xxpr_to_ast_def_expr(rhs3, xdata, iaddr, astree)
237+
238+
if hl_rhs1.is_integer_constant:
239+
addend = cast(AST.ASTIntegerConstant, hl_rhs1).cvalue
240+
addend = addend // tgttypsize
241+
astaddend: AST.ASTExpr = astree.mk_integer_constant(addend)
242+
annotations.append("scaled by " + str(tgttypsize))
243+
return astree.mk_binary_op("plus", hl_rhs2, astaddend)
244+
245+
scale = astree.mk_integer_constant(tgttypsize)
246+
scaled = astree.mk_binary_op("div", hl_rhs1, scale)
247+
return astree.mk_binary_op("plus", hl_rhs2, scaled)
248+
249+
if hl_rhs1_type is not None and hl_rhs1_type.is_pointer:
225250
rhs1tgttyp = cast(AST.ASTTypPtr, hl_rhs1_type).tgttyp
226251
tgttypsize = astree.type_size_in_bytes(rhs1tgttyp)
227252
if tgttypsize is None:
@@ -250,7 +275,7 @@ def pointer_arithmetic_expr() -> AST.ASTExpr:
250275
if hl_rhs2.is_integer_constant:
251276
addend = cast(AST.ASTIntegerConstant, hl_rhs2).cvalue
252277
addend = addend // tgttypsize
253-
astaddend: AST.ASTExpr = astree.mk_integer_constant(addend)
278+
astaddend = astree.mk_integer_constant(addend)
254279
annotations.append("scaled by " + str(tgttypsize))
255280
return astree.mk_binary_op("plus", hl_rhs1, astaddend)
256281

chb/buffer/LibraryCallCallsites.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,31 @@ def lentype(self) -> str:
233233
else:
234234
return lenterm
235235

236+
def to_json_result(self,
237+
dstoffset: int,
238+
buffersize: int,
239+
spare: Optional[str],
240+
) -> JSONResult:
241+
if self.dstarg is None:
242+
chklogger.logger.warning(
243+
"No expression found for destination argument: %s", self)
244+
return JSONResult("librarycallsideeffect", {}, "fail",
245+
"No expression found for destination argument")
246+
content: Dict[str, Any] = {}
247+
content["annotation"] = self.instr.annotation
248+
content["faddr"] = self.faddr
249+
content["iaddr"] = self.instr.iaddr
250+
content["buffersize"] = buffersize
251+
content["target-function"] = self.summary.name
252+
content["stack-offset"] = dstoffset
253+
if self.lenarg is not None:
254+
content["length-argument"] = str(self.lenarg)
255+
else:
256+
content["length-argument"] = None
257+
content["spare"] = spare
258+
259+
return JSONResult("librarycallsideeffect", content, "ok")
260+
236261
def __str__(self) -> str:
237262
return self.instr.iaddr + ": " + str(self.instr.annotation)
238263

chb/cmdline/chkx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,8 +1193,9 @@ def parse() -> argparse.Namespace:
11931193
report_patchcandidates.add_argument(
11941194
"--targets",
11951195
nargs="*",
1196-
default=[],
1197-
help="list of target library functions to include")
1196+
default=['all'],
1197+
help="list of target library functions to include. If not passed, all "
1198+
"library functions found will be included.")
11981199
report_patchcandidates.add_argument(
11991200
"--verbose", "-v",
12001201
action="store_true",

chb/cmdline/reportcmds.py

Lines changed: 75 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@
6666
from chb.util.loggingutil import chklogger
6767

6868
if TYPE_CHECKING:
69-
from chb.api.CallTarget import StubTarget
69+
from chb.api.CallTarget import (
70+
StubTarget, CallTarget)
7071
from chb.api.FunctionStub import SOFunction
7172
from chb.app.AppAccess import AppAccess
7273
from chb.app.BasicBlock import BasicBlock
@@ -990,6 +991,30 @@ def perc(v: float) -> str:
990991
exit(0)
991992

992993

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

9951020
# arguments
@@ -1023,49 +1048,27 @@ def report_buffer_bounds(args: argparse.Namespace) -> NoReturn:
10231048
if calltgt.is_so_target:
10241049
libcalls.add_library_callsite(faddr, baddr, instr)
10251050

1026-
def write_json_result(
1027-
xfilename: Optional[str], jresult: JSONResult) -> None:
1028-
if jresult.is_ok:
1029-
okresult = JU.jsonok("bufferboundsassessment", jresult.content)
1030-
if xfilename is not None:
1031-
filename = xfilename + ".json"
1032-
with open(filename, "w") as fp:
1033-
json.dump(okresult, fp, indent=2)
1034-
chklogger.logger.info("JSON output written to " + filename)
1035-
else:
1036-
print(json.dumps(okresult))
1037-
else:
1038-
failresult = JU.jsonfail(jresult.reason)
1039-
if xfilename is not None:
1040-
filename = xfilename + ".json"
1041-
with open(filename, "w") as fp:
1042-
json.dump(failresult, fp, indent=2)
1043-
chklogger.logger.warning(
1044-
"JSON failure output written to " + filename)
1045-
else:
1046-
print(json.dumps(failresult))
1047-
10481051
if xjson:
10491052
content: Dict[str, Any] = {}
10501053
xinfodata = xinfo.to_json_result()
10511054
if xinfodata.is_ok:
10521055
content["identification"] = xinfodata.content
10531056
else:
1054-
write_json_result(xoutput, xinfodata)
1057+
write_json_result(xoutput, xinfodata, "bufferboundsassessment")
10551058
analysisstats = app.result_metrics.to_json_result()
10561059
if analysisstats.is_ok:
10571060
content["analysis"] = analysisstats.content
10581061
else:
1059-
write_json_result(xoutput, analysisstats)
1062+
write_json_result(xoutput, analysisstats, "bufferboundsassessment")
10601063

10611064
libcallsresult = libcalls.to_json_result()
10621065
if libcallsresult.is_ok:
10631066
content["bounds"] = libcallsresult.content
10641067
else:
1065-
write_json_result(xoutput, libcallsresult)
1068+
write_json_result(xoutput, libcallsresult, "bufferboundsassessment" )
10661069

10671070
write_json_result(xoutput, JSONResult(
1068-
"libcboundsanalysis", content, "ok"))
1071+
"libcboundsanalysis", content, "ok"), "bufferboundsassessment")
10691072

10701073
if not xverbose:
10711074
exit(0)
@@ -1172,20 +1175,35 @@ def find_spare_instruction(
11721175
n_calls: int = 0
11731176
libcalls = LibraryCallCallsites()
11741177

1175-
for (faddr, blocks) in app.call_instructions().items():
1176-
fn = app.function(faddr)
1178+
include_all = xtargets == ['all']
11771179

1180+
def include_target(target: 'CallTarget') -> bool:
1181+
if include_all:
1182+
return True
1183+
return target.name in xtargets
1184+
1185+
for (faddr, blocks) in app.call_instructions().items():
11781186
for (baddr, instrs) in blocks.items():
11791187
for instr in instrs:
11801188
n_calls += 1
11811189
calltgt = instr.call_target
1182-
if calltgt.is_so_target and calltgt.name in xtargets:
1190+
if calltgt.is_so_target and include_target(calltgt):
11831191
libcalls.add_library_callsite(faddr, baddr, instr)
11841192

1185-
print("Number of calls: " + str(n_calls))
1193+
chklogger.logger.debug("Number of calls: %s", n_calls)
11861194

11871195
patchcallsites = libcalls.patch_callsites()
11881196

1197+
content: Dict[str, Any] = {}
1198+
if xjson:
1199+
xinfodata = xinfo.to_json_result()
1200+
if xinfodata.is_ok:
1201+
content["identification"] = xinfodata.content
1202+
else:
1203+
write_json_result(xoutput, xinfodata, "patchcandidates")
1204+
1205+
patch_records = []
1206+
11891207
for pc in sorted(patchcallsites, key=lambda pc:pc.faddr):
11901208
instr = pc.instr
11911209
dstarg = pc.dstarg
@@ -1207,16 +1225,33 @@ def find_spare_instruction(
12071225
basicblock = fn.block(pc.baddr)
12081226
spare = find_spare_instruction(basicblock, instr.iaddr)
12091227

1210-
print(" " + pc.instr.iaddr + " " + pc.instr.annotation)
1211-
print(" - faddr: " + pc.faddr)
1212-
print(" - iaddr: " + pc.instr.iaddr)
1213-
print(" - target function: " + str(pc.summary.name))
1214-
print(" - stack offset: " + str(dstoffset))
1215-
print(" - length argument: " + str(pc.lenarg))
1216-
print(" - buffersize: " + str(buffersize))
1217-
print(" - spare: " + str(spare))
1228+
jresult = pc.to_json_result(dstoffset, buffersize, spare)
1229+
if not jresult.is_ok:
1230+
chklogger.logger.warning("Couldn't process patch callsite %s", pc)
1231+
continue
1232+
1233+
patch_records.append(jresult.content)
1234+
1235+
content["patch-records"] = patch_records
1236+
chklogger.logger.debug("Number of patch callsites: %s", len(content['patch-records']))
1237+
1238+
if xjson:
1239+
jcontent = JSONResult("patchcandidates", content, "ok")
1240+
write_json_result(xoutput, jcontent, "patchcandidates")
1241+
exit(0)
1242+
1243+
for patch_record in content["patch-records"]:
1244+
print(" " + patch_record['iaddr'] + " " + patch_record['annotation'])
1245+
print(" - faddr: %s" % patch_record['faddr'])
1246+
print(" - iaddr: %s" % patch_record['iaddr'])
1247+
print(" - target function: %s" % patch_record['target-function'])
1248+
print(" - stack offset: %s" % patch_record['stack-offset'])
1249+
print(" - length argument: %s" % patch_record['length-argument'])
1250+
print(" - buffersize: %s" % patch_record['buffersize'])
1251+
print(" - spare: %s" % patch_record['spare'])
12181252
print("")
12191253

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

12221257
exit(0)

0 commit comments

Comments
 (0)