Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
start += inst.inst_size
target = self.get_target(offset)
end = self.restrict_to_parent(target, parent)
self.setup_loops[target] = offset
if target != end:
self.fixed_jumps[offset] = end
(line_no, next_line_byte) = self.lines[offset]
jump_back = self.last_instr(
start, end, self.opc.JUMP_ABSOLUTE, next_line_byte, False
)
if jump_back:
jump_forward_offset = xdis.next_offset(
code[jump_back], self.opc, jump_back
)
else:
jump_forward_offset = None
return_val_offset1 = self.prev[self.prev[end]]
if (
jump_back
and jump_back != self.prev_op[end]
and self.is_jump_forward(jump_forward_offset)
):
if code[self.prev_op[end]] == self.opc.RETURN_VALUE or (
code[self.prev_op[end]] == self.opc.POP_BLOCK
and code[return_val_offset1] == self.opc.RETURN_VALUE
):
if not jump_back:
return
jb_inst = self.get_inst(jump_back)
jump_back = self.next_offset(jb_inst.opcode, jump_back)
if_offset = None
if code[self.prev_op[next_line_byte]] not in self.pop_jump_tf:
if_offset = self.prev[next_line_byte]
if if_offset:
loop_type = "while"
self.ignore_if.add(if_offset)
else:
loop_type = "for"
target = next_line_byte
end = xdis.next_offset(code[jump_back], self.opc, jump_back)
else:
if self.get_target(jump_back) >= next_line_byte:
jump_back = self.last_instr(
start, end, self.opc.JUMP_ABSOLUTE, start, False
)
jb_inst = self.get_inst(jump_back)
jb_next_offset = self.next_offset(jb_inst.opcode, jump_back)
if end > jb_next_offset and self.is_jump_forward(end):
if self.is_jump_forward(jb_next_offset):
if self.get_target(jb_next_offset) == self.get_target(end):
self.fixed_jumps[offset] = jb_next_offset
end = jb_next_offset
elif target < offset:
self.fixed_jumps[offset] = jb_next_offset
def next_offset(self, op, offset):
return xdis.next_offset(op, self.opc, offset)
def next_offset(self, op, offset: int) -> int:
return xdis.next_offset(op, self.opc, offset)
targets = {}
for i, inst in enumerate(self.insts):
offset = inst.offset
op = inst.opcode
# Determine structures and fix jumps in Python versions
# since 2.3
self.detect_control_flow(offset, targets, i)
if inst.has_arg:
label = self.fixed_jumps.get(offset)
oparg = inst.arg
if self.version >= 3.6 and self.code[offset] == self.opc.EXTENDED_ARG:
j = xdis.next_offset(op, self.opc, offset)
next_offset = xdis.next_offset(op, self.opc, j)
else:
next_offset = xdis.next_offset(op, self.opc, offset)
if label is None:
if op in self.opc.hasjrel and op != self.opc.FOR_ITER:
label = next_offset + oparg
elif op in self.opc.hasjabs:
if op in self.jump_if_pop:
if oparg > offset:
label = oparg
if label is not None and label != -1:
targets[label] = targets.get(label, []) + [offset]
elif op == self.opc.END_FINALLY and offset in self.fixed_jumps:
label = self.fixed_jumps[offset]
targets[label] = targets.get(label, []) + [offset]
if target > offset:
unop_target = self.last_instr(
offset, target, self.opc.JUMP_FORWARD, target
)
if unop_target and code[unop_target + 3] != self.opc.ROT_TWO:
self.fixed_jumps[offset] = unop_target
else:
self.fixed_jumps[offset] = self.restrict_to_parent(target, parent)
pass
pass
elif self.version >= 3.5:
# 3.5+ has Jump optimization which too often causes RETURN_VALUE to get
# misclassified as RETURN_END_IF. Handle that here.
# In RETURN_VALUE, JUMP_ABSOLUTE, RETURN_VALUE is never RETURN_END_IF
if op == self.opc.RETURN_VALUE:
next_offset = xdis.next_offset(op, self.opc, offset)
if next_offset < len(code) and (
code[next_offset] == self.opc.JUMP_ABSOLUTE
and offset in self.return_end_ifs
):
self.return_end_ifs.remove(offset)
pass
pass
elif op == self.opc.JUMP_FORWARD:
# If we have:
# JUMP_FORWARD x, [non-jump, insns], RETURN_VALUE, x:
# then RETURN_VALUE is not RETURN_END_IF
rtarget = self.get_target(offset)
rtarget_prev = self.prev[rtarget]
if (
code[rtarget_prev] == self.opc.RETURN_VALUE
and rtarget_prev in self.return_end_ifs
if not jump_back:
return
jb_inst = self.get_inst(jump_back)
jump_back = self.next_offset(jb_inst.opcode, jump_back)
if_offset = None
if code[self.prev_op[next_line_byte]] not in self.pop_jump_tf:
if_offset = self.prev[next_line_byte]
if if_offset:
loop_type = "while"
self.ignore_if.add(if_offset)
else:
loop_type = "for"
target = next_line_byte
end = xdis.next_offset(code[jump_back], self.opc, jump_back)
else:
if self.get_target(jump_back) >= next_line_byte:
jump_back = self.last_instr(
start, end, self.opc.JUMP_ABSOLUTE, start, False
)
jb_inst = self.get_inst(jump_back)
jb_next_offset = self.next_offset(jb_inst.opcode, jump_back)
if end > jb_next_offset and self.is_jump_forward(end):
if self.is_jump_forward(jb_next_offset):
if self.get_target(jb_next_offset) == self.get_target(end):
self.fixed_jumps[offset] = jb_next_offset
end = jb_next_offset
elif target < offset:
self.fixed_jumps[offset] = jb_next_offset
if target > offset:
self.fixed_jumps[offset] = target
pass
else:
# FIXME: This is probably a bug in < 3.5 and we should
# instead use the above code. But until we smoke things
# out we'll stick with it.
if rtarget > offset:
self.fixed_jumps[offset] = rtarget
elif self.version < 3.8 and op == self.opc.SETUP_EXCEPT:
target = self.get_target(offset)
end = self.restrict_to_parent(target, parent)
self.fixed_jumps[offset] = end
elif op == self.opc.POP_EXCEPT:
next_offset = xdis.next_offset(op, self.opc, offset)
target = self.get_target(next_offset)
if target > next_offset:
next_op = code[next_offset]
if (
self.opc.JUMP_ABSOLUTE == next_op
and self.opc.END_FINALLY
!= code[xdis.next_offset(next_op, self.opc, next_offset)]
):
self.fixed_jumps[next_offset] = target
self.except_targets[target] = next_offset
elif op == self.opc.SETUP_FINALLY:
target = self.get_target(offset)
end = self.restrict_to_parent(target, parent)
self.fixed_jumps[offset] = end
elif op in self.jump_if_pop:
start += inst.inst_size
target = self.get_target(offset)
end = self.restrict_to_parent(target, parent)
self.setup_loops[target] = offset
if target != end:
self.fixed_jumps[offset] = end
(line_no, next_line_byte) = self.lines[offset]
jump_back = self.last_instr(
start, end, self.opc.JUMP_ABSOLUTE, next_line_byte, False
)
if jump_back:
jump_forward_offset = xdis.next_offset(
code[jump_back], self.opc, jump_back
)
else:
jump_forward_offset = None
return_val_offset1 = self.prev[self.prev[end]]
if (
jump_back
and jump_back != self.prev_op[end]
and self.is_jump_forward(jump_forward_offset)
):
if code[self.prev_op[end]] == self.opc.RETURN_VALUE or (
code[self.prev_op[end]] == self.opc.POP_BLOCK
and code[return_val_offset1] == self.opc.RETURN_VALUE
):