예제 #1
0
    def visitCompare(self, node):
        children = node.getChildren()
        if len(children) == 3:
            left = node.getChildren()[0]
            op = str(node.getChildren()[1])
            if op == "==" or op == "!=":
                right = node.getChildren()[2]
                left_z3 = self.visit(left)
                right_z3 = self.visit(right)
                if z3.is_string(left_z3) and z3.is_string(
                        right_z3) or z3.is_bool(left_z3) and z3.is_bool(
                            right_z3):
                    if op == "==":
                        result = z3.simplify(
                            z3.Not(z3.Distinct(left_z3, right_z3)))
                        return result
                    elif op == "!=":
                        # sys.stderr.write("%s != %s\n" % (left_z3, right_z3))
                        result = z3.simplify(z3.Distinct(left_z3, right_z3))
                        return result
                # elif z3.is_string(left_z3) and z3.is_bool(right_z3):
                #   if op == "==":
                #     pass
                #   elif op == "!=":
                #     pass
                # elif z3.is_bool(left_z3) and z3.is_string(right_z3):
                #   if op == "==":
                #     pass
                #   elif op == "!=":
                #     pass

        # this expression is not supported, so make a predicate variable for it
        predicate = str(node)
        return z3.Bool("PREDICATE_%s" % (predicate))
예제 #2
0
def model_value_to_python(value: z3.ExprRef) -> object:
    if z3.is_string(value):
        return value.as_string()
    elif z3.is_real(value):
        return float(value.as_fraction())
    else:
        return ast.literal_eval(repr(value))
예제 #3
0
def lenOfZ3(obj):
    if type(obj) == str or type(obj) == list:
        return len(obj)

    if z3.is_string(obj):
        return z3.Length(obj)

    raise Exception('Need to calculate length of unknown object')
예제 #4
0
def string_concat(x, args):
    cc = x
    if z3.is_string(x):
        for y in args:
            cc = z3.Concat(cc, createZ3ExpressionFromConstraint(y, {}))
        return cc
    else:
        raise NotSupportedException('We only support concat on stirngs as arrays are difficult in z3.')
예제 #5
0
 def get_z3_value(self, value):
     if z3.is_string(value):
         return value.as_string()[1:-1].replace('\\x00', '?')
     elif z3.is_int(value):
         return value.as_long()
     elif value is None:
         return ''  # TODO adhere to type
     else:
         raise ValueError('Got unknown Z3 type')
예제 #6
0
def coerceTypesIfPossible(var, other_var):
    if z3.is_or(other_var) and not z3.is_bool(var):
        other_var = transformNonBooleanLazyEvaluations(other_var)
    if z3.is_or(var) and not z3.is_bool(other_var):
        var = transformNonBooleanLazyEvaluations(var)

    if z3.is_and(other_var) and not z3.is_bool(var):
        other_var = transformNonBooleanLazyEvaluations(other_var)
    if z3.is_and(var) and not z3.is_bool(other_var):
        var = transformNonBooleanLazyEvaluations(var)
    if var.decl().kind() == z3.Z3_OP_UNINTERPRETED:
        if z3.is_bool(other_var) and not z3.is_bool(var):
            infered_types[str(var)] = 'boolean'
            return z3.Bool(str(var)), other_var
        if z3.is_string(other_var) and not z3.is_string(var):
            if other_var.as_string() == '':
                # we probably dont want to coerce in this specific case as this is merely a non empty check
                if z3.is_bool(var):
                    return var, z3.BoolVal(False)
                if z3.is_int(var):
                    return var, z3.IntVal(0)
            else:
                infered_types[str(var)] = 'string'
                return z3.String(str(var)), other_var
        if z3.is_int(other_var) and not z3.is_int(var):
            infered_types[str(var)] = 'number'
            return z3.Int(str(var)), other_var
    elif var.decl().kind() == z3.Z3_OP_UNINTERPRETED:
        if z3.is_bool(var):
            infered_types[str(var)] = 'boolean'
        if z3.is_string(var):
            infered_types[str(var)] = 'string'
        if z3.is_int(var):
            infered_types[str(var)] = 'number'
    else:
        # this means that it is non-interpreted and we need to coerce other var to the type of var
        if z3.is_string(var) and z3.is_int_value(other_var):
            other_var = z3.StringVal(str(other_var))
        if z3.is_arith(var) and z3.is_string(other_var):
            other_var = z3.IntVal(int(other_var.as_string()))

    return var, other_var
예제 #7
0
 def __k_bool__(self):
     if z3.is_int(self.value) or z3.is_real(self.value) or z3.is_bv(
             self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != 0, self.defaults),
                                         status=True)
     elif z3.is_string(self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != z3.StringVal(""), self.defaults),
                                         status=True)
     else:
         yield inference.InferenceResult(self, status=True)
예제 #8
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())
예제 #9
0
def createZ3ForBool(var):
    if z3.is_int(var):
        return var != z3.IntVal(0)
    elif z3.is_string(var):
        return var != z3.StringVal('')
    elif z3.is_array(var):
        return z3.BoolVal(True)
    elif z3.is_bool(var):
        return var
    elif var is None:
        # this should be the case when we have a JSON value that is just inside a conditional etc
        return None
    elif z3.is_seq(var):
        # not string but still something ref-like we only found cases where this was string comparisons using <, >, etc.
        return var
    else:
        raise Exception('unhandled type in uninterpreted if')
예제 #10
0
def includes(x, args):
    if z3.is_string(x):
        return string_indexOf(x, args) > -1
    elif z3.is_array(x):
        if str(x.decl()) not in ARRAY_LENGTHS:
            raise Exception('We do not know how large the underlying array should be thus we cannot include on it')
        cc = None
        searched = createZ3ExpressionFromConstraint(args[0], {})
        for i in range(ARRAY_LENGTHS[str(x.decl())]):
            c = z3.Select(x, i) == searched
            if cc is None:
                cc = c
            else:
                cc = z3.Or(cc, c)
        return cc
    else:
        raise Exception('What else should we expect to be called includes on instead of strings and arrays')
예제 #11
0
def AssignementsToString(val, model):
    if type(val) == z3.z3.ArrayRef:
        vals = []
        # Just print out the first 5 values of array, we do not really know how
        # many elements need to be in the array due to z3 handling arrays as functions
        for i in range(3):
            vals.append(AssignementsToString(model.eval(val[i]), model))
        return vals
    if z3.is_string(val):
        return val.as_string()
    if z3.is_int(val):
        return int(str(val))
    if z3.is_bool(val):
        if str(val) == 'False':
            return False
        return True

    raise Exception('solved assignement type is neither int nor string, what to do?')
예제 #12
0
def solveConstrains(constraints, types, shouldPrint=True):
    if type(types) == dict:
        addTypesFromTaintAnalysis('event', types['event'])
    else:
        for [iden, typo] in types:
            if type(iden) == str:
                infered_types[iden] = typo
    logging.debug(infered_types)
    c = True
    for constraint in constraints:
        cc = createZ3ForIf(constraint, types)
        logging.debug(cc)
        if z3.is_int(cc):
            cc = cc != 0
        elif z3.is_string(cc):
            cc = cc != z3.StringVal('')
        c = z3.And(c, cc)
    for cc in GLOBAL_CONSTRAINTS:
        logging.debug(cc)

        c = z3.And(c, cc)

    for type_info in infered_types:
        if infered_types[type_info] == '':
            continue
        cc = z3.String('type:' + type_info) == z3.StringVal(infered_types[type_info])
        logging.debug(cc)
        c = z3.And(c, cc)

    for identifier in MAKE_UNSOLVABLE:
        cc = z3.String(identifier) == z3.StringVal('')
        logging.debug(cc)

        c = z3.And(c, cc)

    # solver = z3.SolverFor('QF_LIA')
    solver = z3.Solver()
    solver.add(c)
    r = solver.check()
    if r == z3.unsat:
        if shouldPrint:
            eprint("no solution")
        return 'unsat'
    elif r == z3.unknown:
        if shouldPrint:
            eprint("failed to solve")

        return 'unsat'
        try:
            eprint(solver.model())
        except Exception:
            return
    else:
        model = solver.model()
        assignement = dict()
        types = dict()
        for decl in model.decls():
            if str(decl) == 'event':
                continue
            if str(decl)[:5] == 'type:':
                types[str(decl)[5:]] = AssignementsToString(model.get_interp(decl), model)
            else:
                assignement[str(decl)] = AssignementsToString(model.get_interp(decl), model)
        for identifier in GLOBAL_IDENTIFIER:
            if identifier not in assignement:
                if identifier == 'event':
                    continue
                logging.debug('Adding empty shizzle')
                assignement[identifier] = ''
        logging.debug(GLOBAL_IDENTIFIER)
        if shouldPrint:
            print(json.dumps({'assignements': assignement, 'types': types}))
        return {'assignements': assignement, 'types': types}