1
0
mirror of synced 2024-11-27 23:50:47 +01:00

Fix control flow graph splitting function to handle functions that jump to the end offset as a way of exiting early.

This commit is contained in:
Jennifer Taylor 2021-04-26 01:23:08 +00:00
parent 6323ef9adf
commit 44f5e5cdcc

View File

@ -1037,7 +1037,10 @@ class ByteCodeDecompiler(VerboseOutput):
dest_action = j
break
else:
raise Exception(f"{action} jumps to an opcode that doesn't exist!")
if action.jump_offset == self.bytecode.end_offset:
dest_action = end
else:
raise Exception(f"{action} jumps to an opcode that doesn't exist!")
# If the destination action flow already starts with the jump offset,
# then we're good, we just need to point our current split at this new
@ -1088,7 +1091,10 @@ class ByteCodeDecompiler(VerboseOutput):
dest_action = j
break
else:
raise Exception(f"{action} conditional jumps to an opcode that doesn't exist!")
if action.jump_if_true_offset == self.bytecode.end_offset:
dest_action = end
else:
raise Exception(f"{action} conditional jumps to an opcode that doesn't exist!")
# If the destination action flow already starts with the jump offset,
# then we're good, we just need to point our current split at this new
@ -1136,19 +1142,18 @@ class ByteCodeDecompiler(VerboseOutput):
for start, flow in flows.items():
if start == end:
# We don't want to render out the end of the graph, it was only there to make
# the above algorithm easier.
# the above algorithm easier. We'll add it back later after we fix up the
# chunks based on start_offset, which the end chunk would not have on account
# of containing zero instructions.
continue
if len(flow.next_flow) == 1 and flow.next_flow[0] == end:
# This flow is a termination state.
chunks.append(ByteCodeChunk(self.bytecode.actions[flow.beginning].offset, self.bytecode.actions[flow.beginning:flow.end], []))
else:
next_chunks: List[int] = []
for ano in flow.next_flow:
if ano == end:
raise Exception("Logic error!")
next_chunks: List[int] = []
for ano in flow.next_flow:
if ano == end:
next_chunks.append(self.bytecode.end_offset)
else:
next_chunks.append(self.bytecode.actions[ano].offset)
chunks.append(ByteCodeChunk(self.bytecode.actions[flow.beginning].offset, self.bytecode.actions[flow.beginning:flow.end], next_chunks))
chunks.append(ByteCodeChunk(self.bytecode.actions[flow.beginning].offset, self.bytecode.actions[flow.beginning:flow.end], next_chunks))
# Calculate who points to us as well, for posterity. We can still use chunk.id as
# the offset of the chunk since we haven't converted yet.
@ -1191,7 +1196,9 @@ class ByteCodeDecompiler(VerboseOutput):
chunk.id = chunk_id
chunk_id += 1
end_chunk_id = chunk_id
offset_to_id[self.bytecode.end_offset] = end_chunk_id
# Now, convert the offsets to chunk ID pointers.
end_previous_chunks: List[int] = []
@ -1199,6 +1206,8 @@ class ByteCodeDecompiler(VerboseOutput):
if chunk.next_chunks:
# Normal chunk.
chunk.next_chunks = [offset_to_id[c] for c in chunk.next_chunks]
if end_chunk_id in chunk.next_chunks:
end_previous_chunks.append(chunk.id)
else:
# Point this chunk at the end of bytecode sentinel.
chunk.next_chunks = [end_chunk_id]
@ -1207,7 +1216,6 @@ class ByteCodeDecompiler(VerboseOutput):
# Add the "return" chunk now that we've converted everything.
chunks.append(ByteCodeChunk(end_chunk_id, [], [], previous_chunks=end_previous_chunks))
offset_to_id[self.bytecode.end_offset] = end_chunk_id
return (chunks, offset_to_id)