예제 #1
0
def check_split_induct (p, restrs, hyps, split, tags = None):
	"""perform both the induction check and a function-call based check
	on successes which can avoid some problematic inductions."""
	((l_split, (_, l_step), _), (r_split, (_, r_step), _), _, n, _) = split
	if tags == None:
		tags = p.pairing.tags

	err_hyp = check.split_r_err_pc_hyp (p, split, restrs, tags = tags)
	hyps = [err_hyp] + hyps + check.split_loop_hyps (tags, split,
		restrs, exit = False)

	rep = mk_graph_slice (p)

	if not check.check_split_induct_step_group (rep, restrs, hyps, split,
			tags = tags):
		return False

	l_succs = get_n_offset_successes (rep, l_split, l_step, restrs)
	r_succs = get_n_offset_successes (rep, r_split, r_step, restrs)

	if not l_succs:
		return True

	hyp = syntax.foldr1 (syntax.mk_and, l_succs)
	if r_succs:
		hyp = syntax.mk_implies (foldr1 (syntax.mk_and, r_succs), hyp)

	return rep.test_hyp_whyps (hyp, hyps)
예제 #2
0
	def get_func_assert (self, n_vc, n_vc2):
		(pair, l_n_vc, r_n_vc) = self.get_func_pairing (n_vc, n_vc2)
		(ltag, rtag) = pair.tags
		(inp_eqs, out_eqs) = pair.eqs
		(lin, lout, lsucc) = self.funcs[l_n_vc]
		(rin, rout, rsucc) = self.funcs[r_n_vc]
		lpc = self.get_pc (l_n_vc)
		rpc = self.get_pc (r_n_vc)
		envs = {ltag + '_IN': lin, rtag + '_IN': rin,
			ltag + '_OUT': lout, rtag + '_OUT': rout}
		inp_eqs = inst_eqs (inp_eqs, envs, self.solv)
		out_eqs = inst_eqs (out_eqs, envs, self.solv)
		succ_imp = mk_implies (rsucc, lsucc)

		return mk_implies (foldr1 (mk_and, inp_eqs + [rpc]),
			foldr1 (mk_and, out_eqs + [succ_imp]))
예제 #3
0
	def interpret (self, rep):
		if self.kind == 'PCImp':
			((visit1, tag1), (visit2, tag2)) = self.pcs
			if visit1 == 'Bool':
				pc1 = tag1
			else:
				pc1 = rep.get_pc (visit1, tag = tag1)
			if visit2 == 'Bool':
				pc2 = tag2
			else:
				pc2 = rep.get_pc (visit2, tag = tag2)
			return mk_implies (pc1, pc2)
		elif self.kind == 'Eq':
			[(x, xvis), (y, yvis)] = self.vals
			if self.induct:
				v = rep.get_induct_var (self.induct)
				x = subst_induct (x, v)
				y = subst_induct (y, v)
			x_pc_env = rep.get_node_pc_env (xvis[0], tag = xvis[1])
			y_pc_env = rep.get_node_pc_env (yvis[0], tag = yvis[1])
			if x_pc_env == None or y_pc_env == None:
				return syntax.false_term
			((_, xenv), (_, yenv)) = (x_pc_env, y_pc_env)
			return inst_eq_with_envs ((x, xenv), (y, yenv), rep.solv)
		else:
			assert not 'hypothesis type understood'
예제 #4
0
def find_split_limit (p, n, restrs, hyps, kind, bound = 51, must_find = True,
		hints = [], use_rep = None):
	tag = p.node_tags[n][0]
	trace ('Finding split limit: %d (%s) %s' % (n, tag, restrs))
	trace ('  (restrs = %s)' % (restrs, ))
	trace ('  (hyps = %s)' % (hyps, ), push = 1)
	if use_rep == None:
		rep = mk_graph_slice (p, fast = True)
	else:
		rep = use_rep
	check_order = hints + [i for i in split_sample_set (bound)
		if i not in hints]
	for i in check_order:
		restrs2 = restrs + ((n, VisitCount (kind, i)), )
		pc = rep.get_pc ((n, restrs2))
		restrs3 = restr_others (p, restrs2, 2)
		epc = rep.get_pc (('Err', restrs3), tag = tag)
		hyp = mk_implies (mk_not (epc), mk_not (pc))
		if rep.test_hyp_whyps (hyp, hyps):
			trace ('split limit found: %d' % i, push = -1)
			return i

	trace ('No split limit found for %d (%s).' % (n, tag), push = -1)
	if must_find:
		assert not 'split limit found'
	return None
예제 #5
0
	def hyps_add_model (self, hyps, assert_progress = True):
		if hyps:
			test_expr = foldr1 (mk_and, hyps)
		else:
			# we want to learn something, either a new model, or
			# that all hyps are true. if there are no hyps,
			# learning they're all true is learning nothing.
			# instead force a model
			test_expr = false_term
		test_expr = mk_implies (self.premise, test_expr)
		m = {}
		(r, _) = self.rep.solv.parallel_check_hyps ([(1, test_expr)],
			{}, model = m)
		if r == 'unsat':
			if not hyps:
				trace ('WARNING: SearchKnowledge: premise unsat.')
				trace ("  ... learning procedure isn't going to work.")
				return
			if assert_progress:
				assert not (set (hyps) <= self.facts), hyps
			for hyp in hyps:
				self.facts.add (hyp)
		else:
			assert r == 'sat', r
			self.add_model (m)
			if assert_progress:
				assert self.model_trace[-2:-1] != [m]
예제 #6
0
def get_n_offset_successes (rep, sp, step, restrs):
	loop = rep.p.loop_body (sp)
	ns = [n for n in loop if rep.p.nodes[n].kind == 'Call']
	succs = []
	for i in range (step):
		for n in ns:
			vc = vc_offs (i + 1)
			if n == sp:
				vc = vc_offs (i)
			n_vc = (n, restrs + tuple ([(sp, vc)]))
			(_, _, succ) = rep.get_func (n_vc)
			pc = rep.get_pc (n_vc)
			succs.append (syntax.mk_implies (pc, succ))
	return succs
예제 #7
0
def tryLoopBound(p_n,
                 p,
                 bounds,
                 rep,
                 restrs=None,
                 hints=None,
                 kind='Number',
                 bin_return=False,
                 hyps=None):
    if restrs == None:
        restrs = ()
    if hints == None:
        hints = []
    if hyps == None:
        hyps = []
    tag = p.node_tags[p_n][0]
    from stack_logic import default_n_vc
    print 'trying bound: %s' % bounds
    ret_bounds = []
    for (index, i) in enumerate(bounds):
        print 'testing %d' % i
        restrs2 = restrs + ((p_n, VisitCount(kind, i)), )
        try:
            pc = rep.get_pc((p_n, restrs2))
        except:
            print 'get_pc failed'
            if bin_return:
                return False
            else:
                return -1
        #print 'got rep_.get_pc'
        restrs3 = restr_others(p, restrs2, 2)
        epc = rep.get_pc(('Err', restrs3), tag=tag)
        hyp = mk_implies(mk_not(epc), mk_not(pc))
        hyps = hyps + noHaltHyps(p_n, p)

        #hyps = []
        #print 'calling test_hyp_whyps'
        if rep.test_hyp_whyps(hyp, hyps):
            print 'p_n %d: split limit found: %d' % (p_n, i)
            if bin_return:
                return True
            return index
    if bin_return:
        return False
    print 'loop bound not found!'
    return -1
    assert False, 'failed to find loop bound for p_n %d' % p_n
예제 #8
0
def strengthen_hyp (expr, sign = 1):
	if not expr.kind == 'Op':
		return expr
	if expr.name in ['And', 'Or']:
		vals = [strengthen_hyp (v, sign) for v in expr.vals]
		return syntax.Expr ('Op', expr.typ, name = expr.name,
			vals = vals)
	elif expr.name == 'Implies':
		[l, r] = expr.vals
		l = strengthen_hyp (l, - sign)
		r = strengthen_hyp (r, sign)
		return syntax.mk_implies (l, r)
	elif expr.name == 'Not':
		[x] = expr.vals
		x = strengthen_hyp (x, - sign)
		return syntax.mk_not (x)
	elif expr.name == 'StackEquals':
		if sign == 1:
			return syntax.Expr ('Op', boolT,
				name = 'ImpliesStackEquals', vals = expr.vals)
		else:
			return syntax.Expr ('Op', boolT,
				name = 'StackEqualsImplies', vals = expr.vals)
	elif expr.name == 'ROData':
		if sign == 1:
			return syntax.Expr ('Op', boolT,
				name = 'ImpliesROData', vals = expr.vals)
		else:
			return expr
	elif expr.name == 'Equals' and expr.vals[0].typ == boolT:
		vals = expr.vals
		if vals[1] in [syntax.true_term, syntax.false_term]:
			vals = [vals[1], vals[0]]
		if vals[0] == syntax.true_term:
			return strengthen_hyp (vals[1], sign)
		elif vals[0] == syntax.false_term:
			return strengthen_hyp (syntax.mk_not (vals[1]), sign)
		else:
			return expr
	else:
		return expr
예제 #9
0
def tryLoopBound(p_n, p, bounds, rep, restrs=None, hints=None, kind="Number", bin_return=False, hyps=None):
    if restrs == None:
        restrs = ()
    if hints == None:
        hints = []
    if hyps == None:
        hyps = []
    tag = p.node_tags[p_n][0]
    from stack_logic import default_n_vc

    print "trying bound: %s" % bounds
    ret_bounds = []
    for (index, i) in enumerate(bounds):
        print "testing %d" % i
        restrs2 = restrs + ((p_n, VisitCount(kind, i)),)
        try:
            pc = rep.get_pc((p_n, restrs2))
        except:
            print "get_pc failed"
            if bin_return:
                return False
            else:
                return -1
        # print 'got rep_.get_pc'
        restrs3 = restr_others(p, restrs2, 2)
        epc = rep.get_pc(("Err", restrs3), tag=tag)
        hyp = mk_implies(mk_not(epc), mk_not(pc))
        hyps = hyps + noHaltHyps(p_n, p)

        # hyps = []
        # print 'calling test_hyp_whyps'
        if rep.test_hyp_whyps(hyp, hyps):
            print "p_n %d: split limit found: %d" % (p_n, i)
            if bin_return:
                return True
            return index
    if bin_return:
        return False
    print "loop bound not found!"
    return -1
    assert False, "failed to find loop bound for p_n %d" % p_n
예제 #10
0
def add_model (knowledge, preds):
	(rep, (_, _, _, premise), _, facts) = knowledge
	if preds:
		pred_expr = foldr1 (mk_and, preds)
	else:
		# we want to learn something, either a new model, or that
		# all of our predicates are true. if there are no predicates,
		# ''all our predicates are true'' is trivially true. instead
		# we must want a model (counterexample of false)
		pred_expr = false_term
	m = {}
	r = rep.solv.check_hyp (mk_implies (premise, pred_expr), {}, model = m)
	if r == 'unsat':
		if not preds:
			trace ('WARNING: unsat with no extra assertions.')
			trace ("  ... learning procedure isn't going to work.")
		for pred in preds:
			facts.add (pred)
	else:
		assert r == 'sat'
		update_knowledge_for_model (knowledge, m)
예제 #11
0
	def get_loop_pc_env (self, split, vcount):
		vcount2 = dict (vcount)
		vcount2[split] = vc_num (0)
		vcount2 = tuple (sorted (vcount2.items ()))
		prev_pc_env = self.get_node_pc_env ((split, vcount2))
		if prev_pc_env == None:
			return None
		(_, prev_env) = prev_pc_env
		def av (nm, typ, mem_name = None):
			nm2 = '%s_loop_at_%s' % (nm, split)
			return self.solv.add_var (nm2, typ,
				mem_name = mem_name)
		env = {}
		consts = set ()
		for (nm, typ) in prev_env:
			check_const = self.fast or (typ in
				[builtinTs['HTD'], builtinTs['Dom']])
			if check_const and self.is_synt_const (nm, typ, split):
				env[(nm, typ)] = prev_env[(nm, typ)]
				consts.add ((nm, typ))
			else:
				env[(nm, typ)] = av (nm + '_after', typ,
					('Loop', prev_env[(nm, typ)]))
		for (nm, typ) in prev_env:
			if (nm, typ) in consts:
				continue
			z = self.var_rep_request ((nm, typ), 'Loop',
				(split, vcount), env)
			if z:
				env[(nm, typ)] = z

		pc = mk_smt_expr (av ('pc_of', boolT), boolT)
		if self.fast:
			imp = syntax.mk_implies (pc, prev_pc_env[0])
			self.solv.assert_fact (imp, prev_env,
				unsat_tag = ('LoopPCImp', split))

		return (pc, env)
예제 #12
0
	def interpret_hyp_imps (self, hyps, concl):
		imp = concl
		for h in hyps:
			imp = mk_implies (self.interpret_hyp (h), imp)
		return logic.strengthen_hyp (imp)
예제 #13
0
		if i != head:
			k += 1
		restrs2 = restrs + ((head, vc_num (k)), )
		(pc, env) = rep.get_node_pc_env ((i, restrs2))
		return (to_smt_expr (pc, env, rep.solv),
			to_smt_expr (v_i, env, rep.solv))
	return [get_var (i_offs + (k * i_step))
		for k in [0, 1, 2]]

def expand_var_eqs (knowledge, (v_i, v_j)):
	(rep, (restrs, _, _, _), _, _) = knowledge

	if v_j == 'Const':
		pc_vs = get_var_pc_var_list (knowledge, v_i)
		(_, v0) = pc_vs[0]
		return [mk_implies (pc, mk_eq (v, v0))
			for (pc, v) in pc_vs[1:]]
	# sorting the vars guarantees we generate the same
	# mem eqs each time which is important for the solver
	(v_i, v_j) = sorted ([v_i, v_j])
	pc_vs = zip (get_var_pc_var_list (knowledge, v_i),
		get_var_pc_var_list (knowledge, v_j))
	return [pred for ((pc_i, v_i), (pc_j, v_j)) in pc_vs
		for pred in [mk_eq (pc_i, pc_j),
			mk_implies (pc_i, logic.mk_eq_with_cast (v_i, v_j))]]

word_ops = {'bvadd':lambda x, y: x + y, 'bvsub':lambda x, y: x - y,
	'bvmul':lambda x, y: x * y, 'bvurem':lambda x, y: x % y,
	'bvudiv':lambda x, y: x / y, 'bvand':lambda x, y: x & y,
	'bvor':lambda x, y: x | y, 'bvxor': lambda x, y: x ^ y,
	'bvnot': lambda x: ~ x, 'bvneg': lambda x: - x,
예제 #14
0
    p = rep.p
    tag = p.node_tags[n][0]
    is_C = tag == 'C' or p.hook_tag_hints.get(tag, None) == 'C'
    if not is_C:
        return
    upd_ps = [
        rep.to_smt_expr(ptr, (n, vc))
        for (kind, ptr, v, m) in p.nodes[n].get_mem_accesses()
        if kind == 'MemUpdate'
    ]
    if not upd_ps:
        return
    cache = get_cache(p)
    for ptr in set(upd_ps):
        pc = rep.get_pc((n, vc))
        eq_rodata = rep.solv.get_eq_rodata_witness(ptr)
        hyp = rep.to_smt_expr(syntax.mk_implies(pc, syntax.mk_not(eq_rodata)),
                              (n, vc))
        if ((n, vc), ptr) in cache:
            res = cache[((n, vc), ptr)]
        else:
            res = rep.test_hyp_whyps(hyp, [], cache=cache)
            cache[((n, vc), ptr)] = res
        if res:
            rep.solv.assert_fact(hyp, {})


module_hook_k = 'c_rodata'
target_objects.add_hook('post_emit_node', module_hook_k, hook)
target_objects.use_hooks.add(module_hook_k)