def eval_op(self, node, op_name, *args): """Evaluate an opcode.""" if not self.enabled: return method = getattr(self, op_name, None) if method is None: return self.node = node result = method(*args) # Convert result to an Int instance. if isinstance(result, int): result = types.Int.coerce(result) # Convert result to a Bytes instance. elif isinstance(result, str): result = types.Bytes.coerce(result) result.lineno = node.lineno if not formats.is_strict_num(int(result)): args_str = str(map(str, args))[1:-1] # Remove brackets msg = 'Result of %s is longer than 4 bytes: 0x%x' % ( format_structural_op(node), result) if self.strict_num: self.parent.error(msg, node.lineno) raise IRStrictNumError(msg) else: self.parent.warning(msg, node.lineno) return result
def wrapper(self, *args): args = map(int, args) valid = [formats.is_strict_num(i) for i in args] if False in valid: msg = 'Input value to %s is longer than 4 bytes: 0x%x' % ( method.__name__, args[valid.index(False)]) if self.strict_num: self.parent.error(msg, self.node.lineno) raise IRStrictNumError(msg) else: self.parent.warning(msg, self.node.lineno) return method(self, *args)
def visit_UnaryOpCode(self, node): if SInstructions.is_arithmetic_op(node) and isinstance(node.operand, (structural_nodes.Int, structural_nodes.Bytes)): if not formats.is_strict_num(int(node.operand)): msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, node.operand) if self.options.strict_num: self.error(msg, node.lineno) raise IRStrictNumError(msg) else: self.warning(msg, node.lineno) return_value = self.visit(node.operand) op = types.opcode_by_name(node.name)() return return_value + [op]
def visit_Assignment(self, node): assignment = self.parse_Assignment(node) if isinstance(assignment.value, (structural_nodes.Int, structural_nodes.Bytes)): if not formats.is_strict_num(int(assignment.value)): msg = 'Assignment value to %s is longer than 4 bytes: 0x%x' % (assignment.name, assignment.value) if self.options.strict_num: self.error(msg, assignment.lineno) raise IRStrictNumError(msg) else: self.warning(msg, assignment.lineno) self.add_Assignment(assignment) return None
def visit_BinOpCode(self, node): # Check for values longer than 4 bytes. if SInstructions.is_arithmetic_op(node): operands = [node.left, node.right] if all(isinstance(i, (structural_nodes.Int, structural_nodes.Bytes)) for i in operands): valid = [formats.is_strict_num(int(i)) for i in operands] if False in valid: msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, operands[valid.index(False)]) if self.options.strict_num: self.error(msg, node.lineno) raise IRStrictNumError(msg) else: self.warning(msg, node.lineno) return_value = self.visit(node.left) return_value.extend(self.visit(node.right)) op = types.opcode_by_name(node.name)() return return_value + [op]
def all_strict_nums(numbers): """Evaluate whether instances represent strict numbers.""" return all(formats.is_strict_num(i) for i in map(LInstructions.instruction_to_int, numbers))