def _unary_dunder_operation(self, op_callback): try: result = op_callback(self.value) return inference.InferenceResult(Z3Proxy.init_expr( result, {**self.defaults}), status=True) except z3.Z3Exception: return inference.InferenceResult.load_result(nodes.Uninferable())
def _infer_divmod(node: nodes.Call, context, inferred_attr=None): if len(node.args) != 2: yield inference.InferenceResult.load_result(nodes.Uninferable()) for args in utilities.infer_product(*(arg.infer(context) for arg in node.args)): if all(arg.status and isinstance(arg.result, nodes.Const) for arg in args): try: result = divmod(*(arg.strip_inference_result() for arg in args)) for res in inference.const_factory(result): for a in args: res += a yield res except TypeError: yield inference.InferenceResult.load_result( nodes.Uninferable(), inference_results=args) else: yield inference.InferenceResult.load_result(nodes.Uninferable(), inference_results=args)
def __k_str__(self): try: if z3.is_string(self.value): val = self.value else: val = z3.IntToStr(self.value) return inference.InferenceResult.load_result( Z3Proxy.init_expr(val, {**self.defaults})) except (z3.Z3Exception, Exception): MANAGER.logger.warning( "Can't convert expression of non integer: {} to string", self.value) return inference.InferenceResult.load_result(nodes.Uninferable())
def _compop_dunder_operation(self, op_callback, other: nodes.Const = None): other_defaults = other.defaults if isinstance(other, Z3Proxy) else {} try: other = utilities.make_z3_const( utilities.strip_constant_node(other)) result = op_callback(self.value, other) return inference.InferenceResult(Z3Proxy.init_expr( result, { **self.defaults, **other_defaults }), status=True) except z3.Z3Exception: return inference.InferenceResult.load_result(nodes.Uninferable())
def _default_op( self, op: str, other: inference.InferenceResult, method_name: str, context=None, self_result=inference.InferenceResult, ): try: yield from super(Z3Proxy, self)._default_op(op, other, method_name, context, self_result) except z3.Z3Exception: yield inference.InferenceResult.load_result( nodes.Uninferable(), inference_results=(other, self_result))
def _binop_dunder_operation(self, op: str, op_callback, reflected=False, other: nodes.Const = None): other_defaults = other.defaults if isinstance(other, Z3Proxy) else {} left = self.value right = utilities.make_z3_const(utilities.strip_constant_node(other)) extras = [] if op in ("&", ">>", "<<"): # cast left and right to BitVector for bit operation. left, right = z3.Int2BV(left, 64), z3.Int2BV(right, 64) elif op in ("/", "//"): # special handling divide, due to we have "//" operation in py2 protocol, and # it's incompatible with z3 if op == "//": # convert result to floor. MANAGER.logger.warning( "Z3", "Floor division (//) is not supported and will cast to (/), for node: {}", repr(self)) extras.append(right != 0) op_callback = lambda x, y: x / y elif op == "%": # casting left and right to int before doing modulo if not z3.is_int(left): left = z3.ToInt(left) if not z3.is_int(right): right = z3.ToInt(right) extras.append(right != 0) try: if not reflected: result = op_callback(left, right) else: result = op_callback(right, left) res = inference.InferenceResult(Z3Proxy.init_expr( result, { **self.defaults, **other_defaults }), status=True) res.z3_assumptions |= set(extras) return res except (z3.Z3Exception, TypeError): return inference.InferenceResult.load_result(nodes.Uninferable())
def _infer_bool_op_prm_field(node: nodes.BoolOp, context): """ bool op will convert (a and b and c) to z3.If(bool(a), a, z3.If(bool(b), c)) This assume that `a`, `b`, `c` must have the same sort. """ for vals in utilities.infer_product(*(v.infer(context) for v in node.values)): if any(i.status and isinstance(i.result, Z3Proxy) for i in vals): defaults = {} z3_expr = None broke = False for val in reversed(vals): if val.status and isinstance( val.result, (nodes.Const, nodes.NameConstant)): bool_node = val.result.wrap_bool( ) if node.op == "or" else val.result.invert_condition() MANAGER.add_weak_ref(bool_node) bool_val = next(bool_node.infer(context)) if z3_expr is None: z3_expr = val.strip_inference_result() else: try: z3_expr = z3.If(bool_val.strip_inference_result(), val.strip_inference_result(), z3_expr) except z3.Z3Exception: # sort miss match here, which is caused by python dynamic nature broke = True yield inference.InferenceResult.load_result( nodes.Uninferable(), inference_results=vals) break else: broke = True break if isinstance(val.result, Z3Proxy): defaults.update(val.result.defaults) if not broke: yield inference.InferenceResult(Z3Proxy.init_expr( z3_expr, defaults), status=True, inference_results=vals) else: yield inference.UseDefaultInferenceOnce({"values": vals})
for res in node._infer(context): default_value = res.result if res.status and res.result else None builtin_type = getattr( builtins, res.result_type.name) if res.result_type else None if builtin_type: proxy = Z3Proxy(MANAGER.make_z3_var(node.arg, builtin_type), utilities.strip_constant_node(default_value)) yield inference.InferenceResult(proxy, status=True) else: yield res else: yield from node._infer(context) @decorators.yield_at_least_once( lambda x: inference.InferenceResult.load_result(nodes.Uninferable(x))) @handle_z3_exceptions def _infer_bool_op_prm_field(node: nodes.BoolOp, context): """ bool op will convert (a and b and c) to z3.If(bool(a), a, z3.If(bool(b), c)) This assume that `a`, `b`, `c` must have the same sort. """ for vals in utilities.infer_product(*(v.infer(context) for v in node.values)): if any(i.status and isinstance(i.result, Z3Proxy) for i in vals): defaults = {} z3_expr = None broke = False for val in reversed(vals): if val.status and isinstance(
def wrapper(*args, **kwargs): try: yield from f(*args, **kwargs) except z3.Z3Exception: yield inference.InferenceResult.load_result(nodes.Uninferable())
def __k_float__(self): try: return inference.InferenceResult.load_result( Z3Proxy.init_expr(z3.ToReal(self.value), {**self.defaults})) except z3.Z3Exception: return inference.InferenceResult.load_result(nodes.Uninferable())