Skip to content

Commit f132402

Browse files
committed
ASTI: ensure unique ast instructions per basic block
1 parent 1d210f6 commit f132402

File tree

1 file changed

+32
-3
lines changed

1 file changed

+32
-3
lines changed

chb/astinterface/ASTInterfaceBasicBlock.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,40 @@ def trampoline_payload_roles(self) -> List[str]:
9292

9393
@property
9494
def instructions(self) -> Dict[str, ASTInterfaceInstruction]:
95+
"""Main access to ast representation of instructions.
96+
97+
The ASTInterfaceInstruction provides both the high-level and
98+
low-level representation of an instruction. It is important
99+
to have only one of these per instruction, because the high-level
100+
and low-level representation are created together, and in the
101+
process the relationship between the high-level and low-level
102+
is recorded in the AbstractSyntaxTree/Provenance data structure.
103+
104+
If another instruction is created separately (e.g., to only
105+
obtain the high-level or low-level representation), this
106+
relationship may be corrupted.
107+
108+
Thus, this function should be the only one to create
109+
ASTInterfaceInstruction's.
110+
"""
95111
if len(self._instructions) == 0:
96112
for (iaddr, instr) in self.basicblock.instructions.items():
97113
self._instructions[iaddr] = ASTInterfaceInstruction(instr)
98114
return self._instructions
99115

116+
def has_instruction(self, iaddr: str) -> bool:
117+
return iaddr in self.instructions
118+
119+
def get_instruction(self, iaddr: str) -> ASTInterfaceInstruction:
120+
if self.has_instruction(iaddr):
121+
return self.instructions[iaddr]
122+
else:
123+
raise UF.CHBError(
124+
"No instruction found at address "
125+
+ iaddr +
126+
" in basic block "
127+
+ self.basicblock.baddr)
128+
100129
@property
101130
def trampoline_instructions(
102131
self) -> Dict[str, Dict[str, ASTInterfaceInstruction]]:
@@ -171,8 +200,8 @@ def assembly_ast(self, astree: "ASTInterface") -> AST.ASTStmt:
171200
def ast_fragment(
172201
self, astree: "ASTInterface", frag: "BasicBlockFragment") -> AST.ASTStmt:
173202
if frag.is_predicated:
174-
theninstrs = [ASTInterfaceInstruction(i) for i in frag.thenbranch]
175-
elseinstrs = [ASTInterfaceInstruction(i) for i in frag.elsebranch]
203+
theninstrs = [self.get_instruction(i.iaddr) for i in frag.thenbranch]
204+
elseinstrs = [self.get_instruction(i.iaddr) for i in frag.elsebranch]
176205
thenstmt = self.linear_block_ast(astree, theninstrs)
177206
elsestmt = self.linear_block_ast(astree, elseinstrs)
178207
cinstr = theninstrs[0]
@@ -187,7 +216,7 @@ def ast_fragment(
187216
brcond.exprid, cinstr.iaddr, cinstr.bytestring)
188217
return astree.mk_branch(brcond, thenstmt, elsestmt, "0x0")
189218
else:
190-
instrs = [ASTInterfaceInstruction(i) for i in frag.linear]
219+
instrs = [self.get_instruction(i.iaddr) for i in frag.linear]
191220
return self.linear_ast(astree, instrs)
192221

193222
def fragmented_ast(self, astree: "ASTInterface") -> AST.ASTStmt:

0 commit comments

Comments
 (0)