let rec requires values ki state p = match p.content with
| Pand(p1, p2) ->
let state = requires values ki state p1 in
requires values ki state p2
| (* [state(lval) op term] *)
Prel(rel,
{ term_node = Tapp(f1, _, [ x ]) },
{ term_node = Tapp(f2, _, l) })
when f1.l_var_info.lv_name = state_name
->
(match find_term_loc_or_status values state f2 l with
| None -> warn_todo (); state
| Some sly ->
let subst trans e = fst (Subst.expr ~trans e state.subst) in
let ex = !Properties.Interp.term_to_exp x in
let sx = find_exp_status values state (subst true ex) in
let sx =
if S.use_ctrl_dependencies then
join_deps values state sx
else
sx
in
let sy =
match sly with
| Status s -> s
| Location l -> find_loc_status_with_deps
~with_deps:S.use_ctrl_dependencies
state
l
in
match cmp_of_rel sx sy rel with
| true, true -> assert false
| true, false -> state (* secure *)
| false, b ->
Options.debug "add security leak for %a"
!Ast_printer.d_exp (subst true ex);
let state =
add_leak ~potential:(not b) state ki (subst false ex)
in
if Options.PropagateAssertions.get () then
(* you have just emitted a leak corresponding to a
propertie P, so you can assume that P is verified. Be
careful to only perform over-approximation. *)
match rel with
| Req | Rle ->
(try
let x = !Properties.Interp.term_to_lval x in
change_lval_status values state x sly
with Invalid_argument _ ->
state)
| Rlt | Rgt | Rge | Rneq ->
state
else
state)
| Ptrue -> state
| Pfalse -> state
| _ ->
(* Deal yet only with conjunction of relation. *)
warn_todo ();
state