def offs_expr_const (addr_expr, sp_expr, rep, hyps, extra_defs = {}, cache = None): """if the offset between a stack addr and the initial stack pointer is a constant offset, try to compute it.""" addr_x = solver.parse_s_expression (addr_expr) sp_x = solver.parse_s_expression (sp_expr) vs = [(addr_x, 1), (sp_x, -1)] const = 0 while True: start_vs = list (vs) new_vs = {} for (x, mult) in vs: (var, c) = split_sum_s_expr (x, rep.solv, extra_defs) for v in var: new_vs.setdefault (v, 0) new_vs[v] += var[v] * mult const += c * mult vs = [(x, n) for (x, n) in new_vs.iteritems () if n != 0] if not vs: return const vs = [(simplify_expr_whyps (x, rep, hyps, cache = cache, extra_defs = extra_defs), n) for (x, n) in vs] if sorted (vs) == sorted (start_vs): trace ('offs_expr_const: not const') trace ('%s - %s' % (addr_expr, sp_expr)) trace (str (vs)) last_10_non_const.append ((addr_expr, sp_expr, vs)) del last_10_non_const[:-10] return None
def investigate_funcall_pair(rep, m, l_n_vc, r_n_vc, verbose=False, verbose_imp=False, simplify=True): l_nm = "%s @ %s" % (rep.p.nodes[l_n_vc[0]].fname, rep.node_count_name(l_n_vc)) r_nm = "%s @ %s" % (rep.p.nodes[r_n_vc[0]].fname, rep.node_count_name(r_n_vc)) print 'Attempt match %s -> %s' % (l_nm, r_nm) imp = rep.get_func_assert(l_n_vc, r_n_vc) imp = logic.weaken_assert(imp) if verbose_imp: imp2 = solver.smt_expr(imp, {}, rep.solv) if simplify: imp2 = simplify_sexp(imp2, rep, m) print imp2 assert imp.is_op('Implies'), imp [pred, concl] = imp.vals pred = solver.smt_expr(pred, {}, rep.solv) pred = solver.parse_s_expression(pred) bits = solver.split_hyp_sexpr(pred, []) xs = [eval_model_bool(m, v) for v in bits] print ' %s' % xs for (v, bit) in zip(xs, bits): if v != True or verbose: print ' %s: %s' % (v, bit) if bit[0] == 'word32-eq': vs = [model_sx_word(m, x) for x in bit[1:]] print ' (%s = %s)' % tuple(vs)
def investigate_funcall_pair(rep, m, l_n_vc, r_n_vc, verbose=False, verbose_imp=False, simplify=True): l_nm = "%s @ %s" % (rep.p.nodes[l_n_vc[0]].fname, rep.node_count_name(l_n_vc)) r_nm = "%s @ %s" % (rep.p.nodes[r_n_vc[0]].fname, rep.node_count_name(r_n_vc)) print "Attempt match %s -> %s" % (l_nm, r_nm) imp = rep.get_func_assert(l_n_vc, r_n_vc) if verbose_imp: imp2 = logic.weaken_assert(imp) imp2 = solver.smt_expr(imp2, {}, rep.solv) if simplify: imp2 = simplify_sexp(imp2, rep, m) print imp2 assert imp.is_op("Implies"), imp [pred, concl] = imp.vals pred = solver.smt_expr(pred, {}, rep.solv) pred = solver.parse_s_expression(pred) bits = solver.split_hyp_sexpr(pred, []) xs = [eval_model_bool(m, v) for v in bits] print " %s" % xs for (v, bit) in zip(xs, bits): if v != True or verbose: print " %s: %s" % (v, bit) if bit[0] == "word32-eq": vs = [model_sx_word(m, x) for x in bit[1:]] print " (%s = %s)" % tuple(vs)
def eval(expr, env): try: s = solver.smt_expr(expr, env, rep.solv) s_x = solver.parse_s_expression(s) ev = search.eval_model(m, s_x) return (s, solver.smt_expr(ev, {}, None)) except solver.EnvMiss, e: return None
def get_extra_sp_defs (rep, tag): """all functions will keep the stack pointer equal, whether they have pairing partners or not. add these extra defs/equalities for the purposes of stack depth analysis.""" # FIXME how to parametrise this? sp = mk_var ('r13', syntax.word32T) defs = {} items = [(n_vc, x) for (n_vc, x) in rep.funcs.iteritems () if logic.is_int (n_vc[0])] for ((n, vc), (inputs, outputs, _)) in items: if rep.p.node_tags[n][0] == tag: inp_sp = solver.smt_expr (sp, inputs, rep.solv) inp_sp = solver.parse_s_expression (inp_sp) out_sp = solver.smt_expr (sp, outputs, rep.solv) out_sp = solver.parse_s_expression (out_sp) if inp_sp != out_sp: defs[out_sp] = inp_sp return defs
def eval_model_bool(m, x): if hasattr(x, "typ"): x = solver.smt_expr(x, {}, None) x = solver.parse_s_expression(x) try: r = search.eval_model(m, x) assert r in [syntax.true_term, syntax.false_term], r return r == syntax.true_term except: return "EXCEPT"
def eval_model_bool(m, x): if hasattr(x, 'typ'): x = solver.smt_expr(x, {}, None) x = solver.parse_s_expression(x) try: r = search.eval_model(m, x) assert r in [syntax.true_term, syntax.false_term], r return r == syntax.true_term except: return 'EXCEPT'
def offs_expr_const(addr_expr, sp_expr, rep, hyps, extra_defs={}, cache=None, typ=syntax.word32T): """if the offset between a stack addr and the initial stack pointer is a constant offset, try to compute it.""" addr_x = solver.parse_s_expression(addr_expr) sp_x = solver.parse_s_expression(sp_expr) vs = [(addr_x, 1), (sp_x, -1)] const = 0 while True: start_vs = list(vs) new_vs = {} for (x, mult) in vs: (var, c) = split_sum_s_expr(x, rep.solv, extra_defs, typ=typ) for v in var: new_vs.setdefault(v, 0) new_vs[v] += var[v] * mult const += c * mult vs = [(x, n) for (x, n) in new_vs.iteritems() if n % (2**typ.num) != 0] if not vs: return const vs = [(simplify_expr_whyps(x, rep, hyps, cache=cache, extra_defs=extra_defs), n) for (x, n) in vs] if sorted(vs) == sorted(start_vs): pass # vs = split_merge_ite_sum_sexpr (vs) if sorted(vs) == sorted(start_vs): trace('offs_expr_const: not const') trace('%s - %s' % (addr_expr, sp_expr)) trace(str(vs)) trace(str(hyps)) last_10_non_const.append((addr_expr, sp_expr, vs, hyps)) del last_10_non_const[:-10] return None
def fetch((n, vc)): if n in vds and [(nm, typ) for (nm, typ) in vs if (nm, typ) not in vds[n]]: return None try: (_, env) = rep.get_node_pc_env((n, vc), tag) s = solver.smt_expr(v, env, rep.solv) s_x = solver.parse_s_expression(s) ev = search.eval_model(m, s_x) return (s, solver.smt_expr(ev, {}, None)) except solver.EnvMiss, e: return None
def get_extra_sp_defs(rep, tag): """add extra defs/equalities about stack pointer for the purposes of stack depth analysis.""" # FIXME how to parametrise this? sp = mk_var('r13', syntax.word32T) defs = {} fcalls = [ n_vc for n_vc in rep.funcs if logic.is_int(n_vc[0]) if rep.p.node_tags[n_vc[0]][0] == tag if preserves_sp(rep.p.nodes[n_vc[0]].fname) ] for (n, vc) in fcalls: (inputs, outputs, _) = rep.funcs[(n, vc)] if (sp.name, sp.typ) not in outputs: continue inp_sp = solver.smt_expr(sp, inputs, rep.solv) inp_sp = solver.parse_s_expression(inp_sp) out_sp = solver.smt_expr(sp, outputs, rep.solv) out_sp = solver.parse_s_expression(out_sp) if inp_sp != out_sp: defs[out_sp] = inp_sp return defs
def simplify_sexp(smt_xp, rep, m, flatten=True): if type(smt_xp) == str: smt_xp = solver.parse_s_expression(smt_xp) if smt_xp[0] == "ite": (_, c, x, y) = smt_xp if eval_model_bool(m, c): return simplify_sexp(x, rep, m, flatten) else: return simplify_sexp(y, rep, m, flatten) if type(smt_xp) == tuple: smt_xp = tuple([simplify_sexp(x, rep, m, False) for x in smt_xp]) if flatten: return solver.flat_s_expression(smt_xp) else: return smt_xp
def simplify_sexp(smt_xp, rep, m, flatten=True): if type(smt_xp) == str: smt_xp = solver.parse_s_expression(smt_xp) if smt_xp[0] == 'ite': (_, c, x, y) = smt_xp if eval_model_bool(m, c): return simplify_sexp(x, rep, m, flatten) else: return simplify_sexp(y, rep, m, flatten) if type(smt_xp) == tuple: smt_xp = tuple([simplify_sexp(x, rep, m, False) for x in smt_xp]) if flatten: return solver.flat_s_expression(smt_xp) else: return smt_xp
def func_assert_premise_strength(rep, m, l_n_vc, r_n_vc): imp = rep.get_func_assert(l_n_vc, r_n_vc) assert imp.is_op('Implies'), imp [pred, concl] = imp.vals pred = solver.smt_expr(pred, {}, rep.solv) pred = solver.parse_s_expression(pred) bits = solver.split_hyp_sexpr(pred, []) assert bits, bits scores = [] for bit in bits: try: res = eval_model_bool(m, bit) if res: scores.append(1.0) else: scores.append(0.0) except solver.EnvMiss, e: scores.append(0.5) except AssertionError, e: scores.append(0.5)
def unfold_defs(defs, hyp, depthlimit=-1): return solver.flat_s_expression(unfold_defs_sexpr(defs, solver.parse_s_expression(hyp), depthlimit))
def eval_model_expr (m, solv, v): s = solver.smt_expr (v, {}, solv) s_x = solver.parse_s_expression (s) return eval_model (m, s_x)
def unfold_defs(defs, hyp, depthlimit=-1): return solver.flat_s_expression( unfold_defs_sexpr(defs, solver.parse_s_expression(hyp), depthlimit))