def get_models(F, M): result = [] s = z3.Solver() s.add(F) print(s) while len(result) < M and s.check() == z3.sat: m = s.model() result.append(m) # Create a new constraint the blocks the current model block = [] for d in m: # XXX: hack. Should not be possible to change f without R,C changes... if str(d).startswith('f_'): continue # d is a declaration if d.arity() > 0: raise z3.Z3Exception("uninterpreted functions are not supported") # create a constant from declaration c = d() if z3.is_array(c) or c.sort().kind() == z3.Z3_UNINTERPRETED_SORT: raise z3.Z3Exception("arrays and uninterpreted sorts are not supported") block.append(c != m[d]) s.add(z3.Or(block)) return result
def get_models(F, M): result = [] s = z3.Solver() s.add(F) print(s) while len(result) < M and s.check() == z3.sat: m = s.model() result.append(m) # Create a new constraint the blocks the current model block = [] for d in m: # XXX: hack. Should not be possible to change f without R,C changes... if str(d).startswith('f_'): continue # d is a declaration if d.arity() > 0: raise z3.Z3Exception( "uninterpreted functions are not supported") # create a constant from declaration c = d() if z3.is_array(c) or c.sort().kind() == z3.Z3_UNINTERPRETED_SORT: raise z3.Z3Exception( "arrays and uninterpreted sorts are not supported") block.append(c != m[d]) s.add(z3.Or(block)) return result
def main(): x = z3.BitVec('x', 8) y = z3.BitVec('y', 8) s = z3.Solver() s.add(((x << 2) + (3 * y)) == z3.BitVecVal(0x41, 8)) s.add(((x >> 4) - (y << 2)) > z3.BitVecVal(0x10, 8)) s.add(((x * 5) - (y * 2)) > z3.BitVecVal(0x42, 8)) s.add(x != z3.BitVecVal(0, 8)) s.add(y != z3.BitVecVal(0, 8)) while s.check() == z3.sat: # Get a model satisfying the rules. model = s.model() # Do something with the model print model # Prevent the same model from showing up again. block = [] for instance in model: if instance.arity() > 0: raise z3.Z3Exception( "uninterpreted functions are not supported") constant = instance() if z3.is_array(constant) or constant.sort().kind( ) == z3.Z3_UNINTERPRETED_SORT: raise Z3Exception( "arrays and uninterpreted sorts are not supported") block.append(constant == model[instance]) inverted_block = z3.Not(z3.And(block)) s.add(inverted_block)
def string_indexOf(x, args): if 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') helper_int = z3.Int('__ignore_arr_indexOf_helper_' + randomString()) search_string = createZ3ExpressionFromConstraint(args[0], {}) all = [] presentImplications = [] for i in range(ARRAY_LENGTHS[str(x.decl())]): conditional = z3.Select(x, i) == search_string all.append(conditional) true_imply = z3.Implies(conditional, helper_int <= i) false_imply = z3.Implies(z3.Not(conditional), helper_int > i) presentImplications.append(true_imply) presentImplications.append(false_imply) all = z3.Or(all) GLOBAL_CONSTRAINTS.append(z3.And(z3.Implies(all, z3.And(presentImplications)), z3.Implies(all, helper_int >= 0), z3.Implies(z3.mk_not(all), helper_int == -1))) return helper_int else: if len(args) > 1: return z3.IndexOf(x, createZ3ExpressionFromConstraint(args[0], {}), createZ3ExpressionFromConstraint(args[1], {})) else: return z3.IndexOf(x, createZ3ExpressionFromConstraint(args[0], {}), 0)
def resolveOpsOnParent(op_obj, types): # this is parent or nothing if len(op_obj['old_ops']) < 1: return None val = createZ3ExpressionFromConstraint({'identifier': op_obj['old_identifier'], 'ops': op_obj['old_ops']}, types) if val is None or (val.decl().kind() == z3.Z3_OP_UNINTERPRETED and not z3.is_array(val)): # this is the case when the parent elems have no ops on them return None if z3.is_bool(val) and len(val.children()) and val.children()[0].decl().kind() == z3.Z3_OP_UNINTERPRETED: return None val = transformNonBooleanLazyEvaluations(val) return val
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')
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')
def get_models(self, limit=10): s = z3.Solver() s.add(self.constraints) i = 0 while i < limit and s.check() == z3.sat: m = s.model() yield i, m, s.statistics() i += 1 block = [] for d in m: # d is a declaration # ignore room differences in schedules if d.arity() <= 0 and not d.name().endswith( 'room') and not d.name().endswith('lab'): # create a constant from declaration c = d() if not z3.is_array( c) and c.sort().kind() != z3.Z3_UNINTERPRETED_SORT: block.append(c == m[d]) s.add(z3.simplify(z3.Not(z3.And(*block))))
def get_models(F, M): result = [] s = z3.Solver() s.add(F) while len(result) < M and s.check() == z3.sat: m = s.model() result.append(m) # Create a new application the blocks the current model block = [] for d in m: # d is a declaration if d.arity() > 0: raise z3.Z3Exception("uninterpreted functions are not supported") # create a constant from declaration c = d() if z3.is_array(c) or c.sort().kind() == z3.Z3_UNINTERPRETED_SORT: raise z3.Z3Exception("arrays and uninterpreted sorts are not supported") block.append(c != m[d]) s.add(z3.Or(block)) return(result)
def get_models(F, M=10): s = z3.Solver() s.add(F) i = 0 while i < M and s.check() == z3.sat: m = s.model() yield i, m i += 1 block = [] for d in m: # d is a declaration # ignore room differences in schedules if d.arity() <= 0 and not d.name().endswith('room'): # create a constant from declaration c = d() if not z3.is_array( c) and c.sort().kind() != z3.Z3_UNINTERPRETED_SORT: block.append(c == m[d]) s.add(z3.simplify(z3.Not(z3.And(*block)))) else: # failed or limit -- print stats of last check print(s.statistics())
def get_models(F): result = [] s = Solver() s.add(F) while True: if s.check() == sat: m = s.model() result.append(m) # Create a new constraint the blocks the current model block = [] for d in m: # d is a declaration if d.arity() > 0: raise Z3Exception( "uninterpreted functions are not suppported") # create a constant from declaration c = d() if is_array(c) or c.sort().kind() == Z3_UNINTERPRETED_SORT: raise Z3Exception( "arrays and uninterpreted sorts are not supported") block.append(c != m[d]) s.add(Or(block)) else: return result
def createZ3ExpressionFromConstraint(constraint, types, emitParentConstraint=True): if type(constraint) != dict: if type(constraint) == str: return z3.StringVal(constraint) if type(constraint) == int: return z3.IntVal(constraint) if type(constraint) == bool: return z3.BoolVal(constraint) if constraint is None: return None raise Exception('Dealing with non-int non-string basic values, aborting!', constraint) if 'type' not in constraint: if 'isRealValue' in constraint: if 'value' in constraint: var = getZ3ValFromJSVal(constraint['value']) elif 'val' in constraint: var = getZ3ValFromJSVal(constraint['val']) else: raise Exception('Should not encounter realValue without reference to the real value...') else: if 'identifier' in constraint: var = getTypedZ3ValFromIdentifier(constraint['identifier'], types) else: # probably the empty object when we have something || {} return None for op in constraint['ops']: if 'val' not in op: op['val'] = '' if op['type'] == 'ops_on_parent_element': val = resolveOpsOnParent(op, types) if z3.is_array(val): accesed = constraint['identifier'].split('.')[-1] if accesed == 'length': raise NotSupportedException( 'z3 cannot use the length of arrays due to their representation as functions') if int(accesed) < 0 and str(val.decl()) in ARRAY_LENGTHS: var = z3.Select(val, ARRAY_LENGTHS[str(val.decl())] + int(accesed)) else: var = z3.Select(val, int(accesed)) elif val is not None: key = str(val) if key not in identifier_substitutions: identifier_substitutions[key] = '__substitute_values_' + randomString() identifier = identifier_substitutions[key] GLOBAL_CONSTRAINTS.append(val == z3.StringVal(identifier)) accesed = constraint['identifier'].split('.')[-1] if accesed == 'length': var = z3.Length(z3.String(identifier)) else: var = z3.String(identifier + '.' + accesed) # GLOBAL_CONSTRAINTS.append(var == val) elif op['type'] == 'member_function': var = transformNonBooleanLazyEvaluations(var) if op['function_name'] in StringFunctions: var = StringFunctions[op['function_name']](var, op['args']) elif op['function_name'] in ArrayFunctions: var = ArrayFunctions[op['function_name']](var, op['args']) else: if op['function_name'] in ['call', 'apply', 'bind']: raise NotSupportedException('We do not support function calls over function pointer') raise Exception('String function not supported! ' + op['function_name']) elif op['type'] == 'Binary': other_var = createZ3ExpressionFromConstraint(op['val'], types) if other_var is None: # this is the case when we compare something to null if op['op'] == '===' or op['op'] == '==': var = createZ3ForBool(var) var = z3.Not(var) continue var, other_var = coerceTypesIfPossible(var, other_var) changed = checkForTypeEqualToString(var, other_var, op) if changed is not None: var = changed elif op['side'] == 'left': var = BinaryFunctions[op['op']](var, other_var) elif op['side'] == 'right': var = BinaryFunctions[op['op']](other_var, var) else: var = BinaryFunctions[op['op']](var, other_var) elif op['type'] == 'Unary': var = UnaryFunctions[op['op']](var) elif op['type'] == 'iterator': if z3.is_array(var): var = z3.Select(var, op['accessed_elem']) else: raise Exception('This should always be an array', var, infered_types) elif op['type'] == 'external_function': if op['function_name'] == 'JSON.parse': infered_types[constraint['identifier']] = 'JSON' var = z3.String(constraint['identifier']) else: logging.debug('Arbitrary external functions not yet support ' + op['function_name']) elif op['type'] == 'Logical': if op['side'] == 'left' or op['side'] == 'both': l_c = createZ3ForBool(var) r_c = createZ3ForBool(createZ3ExpressionFromConstraint(op['val'], types)) else: l_c = createZ3ForBool(createZ3ExpressionFromConstraint(op['val'], types)) r_c = createZ3ForBool(var) if l_c is None or r_c is None: if l_c is None: var = r_c if r_c is None: var = l_c continue if op['op'] == '&&': var = z3.And(l_c, r_c) else: var = z3.Or(l_c, r_c) else: logging.debug('Not supported type ' + op['type']) return var elif constraint['type'] == 'Logical': l_c = createZ3ForBool(createZ3ExpressionFromConstraint(constraint['l_val'], types)) r_c = createZ3ForBool(createZ3ExpressionFromConstraint(constraint['r_val'], types)) if l_c is None or r_c is None: return l_c or r_c if constraint['op'] == '&&': return z3.And(l_c, r_c) else: return z3.Or(l_c, r_c) elif constraint['type'] == 'Binary': return BinaryFunctions[constraint['op']](createZ3ExpressionFromConstraint(constraint['l_val'], types), createZ3ExpressionFromConstraint(constraint['r_val'], types)) elif constraint['type'] == 'Unary': return UnaryFunctions[constraint['op']](createZ3ExpressionFromConstraint(constraint['val'], types)) else: raise Exception('Unexpected constraint type')