@@ -7,24 +7,25 @@ use array.Array
77use option.Option
88use ref.Ref
99use int.Int
10+ use witness.Witness
1011
1112(* loose models for the types in sudoers::Ast *)
1213type metavar 'a = All | Only 'a
13- type qualified 'a = Yes 'a | No 'a
14+ type qualified 'a = Allow 'a | Forbid 'a
1415type spec 'tag 'a = { inner: qualified (metavar 'a); info: 'tag }
1516
1617predicate contains (pred: 'a -> bool) (a: array 'a)
1718 = exists i. 0 <= i < length a /\ pred a[i]
1819
1920function who (item: spec 'tag 'a): metavar 'a
2021 = match item.inner with
21- | Yes x -> x
22- | No x -> x
22+ | Allow x -> x
23+ | Forbid x -> x
2324 end
2425
2526function condition (item: spec 'tag 'a): option 'tag
2627 = match item with
27- | { inner = Yes _; info = tag } -> Some tag
28+ | { inner = Allow _; info = tag } -> Some tag
2829 | _ -> None
2930 end
3031
@@ -37,14 +38,17 @@ function matched_by (pred: 'a -> bool) (item: spec 'tag 'a): bool
3738let function bool_then (b: bool) (x: 'a): option 'a
3839 = if b then Some x else None
3940
40- predicate final_match (pred: 'a -> bool) (a: array 'a) (f: 'a -> 'b) (x: 'b)
41- = exists i. 0 <= i < length a /\ pred a[i] /\ f a[i] = x /\ forall k. i < k < length a -> not pred a[k]
41+ predicate is_final_match (pred: 'a -> bool) (a: array 'a) (i: int)
42+ = 0 <= i < length a /\ pred a[i] /\ forall k. i < k < length a -> not pred a[k]
43+
44+ function final_match (pred: 'a -> bool) (items: array 'a): 'a
45+ = items[witness (is_final_match pred items)]
4246
4347(* Why3 model of the sudoers::find_item function *)
4448let find_item (items: array (spec 'tag 'a)) (pred: 'a -> bool): option 'tag
4549 returns {
46- | Some tag -> final_match (matched_by pred) items condition (Some tag)
47- | None -> not contains (matched_by pred) items \/ final_match (matched_by pred) items condition None
50+ | Some tag -> contains (matched_by pred) items && condition (final_match (matched_by pred) items) = Some tag
51+ | None -> contains (matched_by pred) items -> condition ( final_match (matched_by pred) items) = None
4852 }
4953
5054= let result = ref None in
@@ -54,13 +58,13 @@ let find_item (items: array (spec 'tag 'a)) (pred: 'a -> bool): option 'tag
5458 exists j. 0 <= j < i /\ matched_by pred items[j] /\ Some tag = condition items[j] /\
5559 forall k. j < k < i -> not matched_by pred items[k] }
5660 let (judgement, who) = match items[i].inner with
57- | No x -> (false, x)
58- | Yes x -> (true, x)
61+ | Forbid x -> (false, x)
62+ | Allow x -> (true, x)
5963 end in
6064 let info = items[i].info in
6165 match who with
6266 | All -> result := judgement.bool_then(info)
63- | Only id -> if pred id then result := judgement.bool_then(info);
67+ | Only id -> if pred id then result := judgement.bool_then(info)
6468 end;
6569 done;
6670
0 commit comments