Beispiel #1
0
 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)
Beispiel #3
0
 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())
Beispiel #4
0
 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())
Beispiel #5
0
 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))
Beispiel #6
0
    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(
Beispiel #9
0
 def wrapper(*args, **kwargs):
     try:
         yield from f(*args, **kwargs)
     except z3.Z3Exception:
         yield inference.InferenceResult.load_result(nodes.Uninferable())
Beispiel #10
0
 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())