Skip to content

Commit c25aab3

Browse files
committed
CHC: merge result-value migration with Errno changes
1 parent 715a562 commit c25aab3

3 files changed

Lines changed: 73 additions & 47 deletions

File tree

CodeHawk/CHC/cchanalyze/cCHCallTranslator.ml

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,21 @@ let is_assert_fail_function fname = fname = "__assert_fail"
8787

8888
let is_library_function (fname:string): bool =
8989
if CCHDeclarations.cdeclarations#has_varinfo_by_name fname then
90-
let varinfo = CCHDeclarations.cdeclarations#get_varinfo_by_name fname in
91-
(* starts with '/' ? *)
92-
match String.index_opt varinfo.vdecl.file '/' with
93-
| Some i -> i = 0
94-
| _ -> false
90+
TR.tfold
91+
~ok:(fun varinfo ->
92+
(* starts with '/' ? *)
93+
match String.index_opt varinfo.vdecl.file '/' with
94+
| Some i -> i = 0
95+
| _ -> false)
96+
~error:(fun err ->
97+
begin
98+
log_error_result
99+
~tag:"is_library_function"
100+
__FILE__ __LINE__
101+
[String.concat ", " err];
102+
false
103+
end)
104+
(CCHDeclarations.cdeclarations#get_varinfo_by_name fname)
95105
else
96106
false
97107

@@ -217,8 +227,8 @@ let is_not_writes_errno x = not (is_writes_errno x)
217227
let has_writes_errno = List.exists is_writes_errno
218228

219229
let disjoint (p : annotated_xpredicate_t) (q : annotated_xpredicate_t) =
220-
let int_of_ret op c =
221-
match op with
230+
let int_of_ret op c =
231+
match op with
222232
| Eq -> CHIntervals.mkInterval c c
223233
| Lt -> new CHIntervals.interval_t CHBounds.minus_inf_bound (CHBounds.bound_of_num (c#sub numerical_one))
224234
| Le -> new CHIntervals.interval_t CHBounds.minus_inf_bound (CHBounds.bound_of_num c)
@@ -230,7 +240,7 @@ let disjoint (p : annotated_xpredicate_t) (q : annotated_xpredicate_t) =
230240
match fst p, fst q with
231241
| XNull ReturnValue, XNotNull ReturnValue -> true
232242

233-
| XRelationalExpr (op, ReturnValue, NumConstant v),
243+
| XRelationalExpr (op, ReturnValue, NumConstant v),
234244
XRelationalExpr (op', ReturnValue, NumConstant v') ->
235245
let pi = int_of_ret op v in
236246
let qi = int_of_ret op' v' in
@@ -1520,17 +1530,17 @@ object (self)
15201530
let unknownSym = CCHErrnoWritePredicateSymbol.to_symbol CCHErrnoWritePredicateSymbol.Unknown in
15211531
List.map (fun v -> make_c_cmd (ASSIGN_SYM (v, SYM unknownSym))) env#get_errno_write_vars
15221532

1523-
method private get_errno_sideeffect
1533+
method private get_errno_sideeffect
15241534
(fname: string)
1525-
(postconditions: annotated_xpredicate_t list * annotated_xpredicate_t list)
1535+
(postconditions: annotated_xpredicate_t list * annotated_xpredicate_t list)
15261536
(optrvar: variable_t option) =
1527-
let (pcs, epcs) = postconditions in
1537+
let (pcs, epcs) = postconditions in
15281538

1529-
if not (is_library_function fname) then
1539+
if not (is_library_function fname) then
15301540
self#havoc_errno_write
1531-
else
1541+
else
15321542

1533-
let non_errno_pcs, non_errno_epcs =
1543+
let non_errno_pcs, non_errno_epcs =
15341544
List.filter is_not_writes_errno pcs, List.filter is_not_writes_errno epcs in
15351545

15361546
let rv_interval op c =
@@ -1544,12 +1554,12 @@ object (self)
15441554
in
15451555

15461556
(* We want to make sure that the success and failure cases are disjoint, otherwise
1547-
we may be able to prove that errno was written in the success case even though it wasn't specified.
1557+
we may be able to prove that errno was written in the success case even though it wasn't specified.
15481558
This is almost certainly an error in the specification, but we don't want that error to propagate here. *)
15491559
let success_no_write p = List.exists (disjoint p) non_errno_pcs in
15501560

1551-
let errno_sideeffect =
1552-
if has_writes_errno epcs then
1561+
let errno_sideeffect =
1562+
if has_writes_errno epcs then
15531563
match optrvar, non_errno_epcs with
15541564
| Some rvar, [XNull ReturnValue, _ as p] when success_no_write p ->
15551565
let idx = rvar#getName#getSeqNumber in
@@ -1562,18 +1572,18 @@ object (self)
15621572
let idxNullSym = CCHErrnoWritePredicateSymbol.to_symbol (CCHErrnoWritePredicateSymbol.VarInt(idx, lb, ub)) in
15631573
[ make_c_cmd (ASSIGN_SYM (env#get_errno_write_var context, SYM idxNullSym)) ]
15641574

1565-
| _ ->
1575+
| _ ->
15661576
[]
15671577
else
15681578
[]
1569-
1579+
15701580
in errno_sideeffect
15711581

15721582
method private get_sideeffect
15731583
(fname:string)
15741584
(fvid:int)
15751585
(args:exp list)
1576-
(fnargs:xpr_t list)
1586+
(fnargs:xpr_t list)
15771587
optrvar
15781588
=
15791589
let vinfo = TR.tget_ok (fdecls#get_varinfo_by_vid fvid) in

CodeHawk/CHC/cchanalyze/cCHExpTranslator.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ object (self)
305305
match op with
306306
| Neg -> XOp (XNeg, [self#translate_expr x])
307307
| BNot -> XOp (XBNot, [self#translate_expr x])
308-
| LNot when is_pointer_type (type_of_exp fdecls x) ->
308+
| LNot when TR.tfold_default is_pointer_type false (type_of_exp fdecls x) ->
309309
XOp (XEq, [self#translate_expr x; XConst (IntConst numerical_zero)])
310310
| LNot -> XOp (XLNot, [self#translate_expr x])
311311

@@ -904,7 +904,8 @@ object (self)
904904
| CastE (_, e) -> is_zero e
905905
| _ -> false in
906906
match cond with
907-
| UnOp (LNot, (Lval lval as e), _) when is_pointer_type (type_of_exp fdecls e) ->
907+
| UnOp (LNot, (Lval lval as e), _)
908+
when (TR.tfold_default is_pointer_type false (type_of_exp fdecls e)) ->
908909
let symvar = self#translate_lhs_lval lval in
909910
if symvar#isTmp then
910911
(SKIP, SKIP)

CodeHawk/CHC/cchpre/cCHCreateErrnoPOs.ml

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ open CHPretty
3030
open CHUtils
3131

3232
(* chtuil *)
33+
open CHLogger
3334
open CHTimingLog
3435
open CHTraceResult
3536

@@ -48,9 +49,11 @@ open CCHPreTypes
4849
open CCHProofScaffolding
4950

5051
module H = Hashtbl
52+
module TR = CHTraceResult
53+
5154
let (let* ) x f = CHTraceResult.tbind f x
5255

53-
let result_of_option (msg: string) (o: 'a option): ('a, string list) result =
56+
let result_of_option (msg: string) (o: 'a option): ('a, string list) result =
5457
match o with
5558
| None -> Error [msg]
5659
| Some r -> Ok r
@@ -65,11 +68,23 @@ let is_errno_location_call (e:exp): bool =
6568
| _ -> false
6669

6770
let is_int_ptr (env: cfundeclarations_int) (v: int): bool =
68-
let ty = (env#get_varinfo_by_vid v).vtype in
69-
let ty_unroll = CCHFileEnvironment.file_environment#get_type_unrolled ty in
70-
match ty_unroll with
71-
| TPtr (TInt _, _) -> true
72-
| _ -> false
71+
TR.tfold
72+
~ok:(fun vinfo ->
73+
let ty = vinfo.vtype in
74+
let ty_unroll = CCHFileEnvironment.file_environment#get_type_unrolled ty in
75+
match ty_unroll with
76+
| TPtr (TInt _, _) -> true
77+
| _ -> false)
78+
~error:(fun err ->
79+
begin
80+
log_error_result
81+
~tag:"is_int_ptr"
82+
~msg:env#functionname
83+
__FILE__ __LINE__
84+
[String.concat ", " err];
85+
false
86+
end)
87+
(env#get_varinfo_by_vid v)
7388

7489
(* Collect all pointers `x` from a target expression that have non-deref uses *)
7590
class pointer_use_expr_walker_t (env:cfundeclarations_int) =
@@ -93,9 +108,9 @@ let blacklistable_pointers_of_exp (env: cfundeclarations_int) (e: exp): int list
93108
let walker = new pointer_use_expr_walker_t env in
94109
let _ = walker#walk_exp e in
95110
walker#get_vars
96-
97-
(* Collect all variables that must alias __errno_location(). This fails if
98-
we see anything that makes this analysis non-trivial,
111+
112+
(* Collect all variables that must alias __errno_location(). This fails if
113+
we see anything that makes this analysis non-trivial,
99114
like x = __errno_location(); y = x; ... *)
100115
class errno_location_block_walker_t (env:cfundeclarations_int) =
101116
object (self)
@@ -104,29 +119,29 @@ object (self)
104119
(* vids *)
105120
val errno_pointers = new IntCollections.set_t
106121

107-
(*
122+
(*
108123
These are vids of pointers, x, whose uses in the program are anything _EXCEPT_
109124
1) x = __errno_location()
110125
2) *x
111126
112127
e.g. the following instructions or expressions would result in adding x
113128
to this set:
114-
y = x, x + 1,
129+
y = x, x + 1,
115130
*)
116131
val blacklist_pointers = new IntCollections.set_t
117132

118133
method invalid_errno_uses: IntCollections.set_t =
119134
errno_pointers#inter blacklist_pointers
120-
135+
121136
method errno_pointers: IntCollections.set_t = errno_pointers
122137

123138
method! walk_instr (i:instr) =
124139
match i with
125-
| Call (Some (Var x, _), f, [], _) when is_errno_location_call f ->
140+
| Call (Some (Var x, _), f, [], _) when is_errno_location_call f ->
126141
self#add_errno_pointer (snd x);
127142
super#walk_instr i
128143

129-
| _ ->
144+
| _ ->
130145
super#walk_instr i
131146

132147
method! walk_rhs (e:exp) = self#blacklist_exp_ptrs e
@@ -146,15 +161,15 @@ object (self)
146161
end
147162

148163
(* Check that we can easily track aliases of __errno_location() *)
149-
let check_errno_pointer_uses_in_block (env: cfundeclarations_int) (b: block) =
164+
let check_errno_pointer_uses_in_block (env: cfundeclarations_int) (b: block) =
150165
let block_walker = new errno_location_block_walker_t env in
151166
let _ = block_walker#walk_block b in
152167
if (block_walker#invalid_errno_uses)#isEmpty then
153168
Some (block_walker#errno_pointers)
154169
else
155170
None
156171

157-
(* At every *read* of errno, check that we *must* observe a known local write, where
172+
(* At every *read* of errno, check that we *must* observe a known local write, where
158173
such a write is either:
159174
1) a direct assignment (e.g. errno = 0)
160175
2) a write due to a library call (e.g. fopen in the branch where fopen returned NULL)
@@ -169,7 +184,7 @@ object (self)
169184
self#create_po_block (mk_program_context ()) self#f.sbody
170185

171186
method private create_po_block (context: program_context_int) (b: block): unit=
172-
List.iter (fun s -> self#create_po_stmt (context#add_stmt s.sid) s) b.bstmts
187+
List.iter (fun s -> self#create_po_stmt (context#add_stmt s.sid) s) b.bstmts
173188

174189
method private create_po_stmt (context: program_context_int) (s: stmt): unit =
175190
self#create_po_stmtkind context s.skind
@@ -203,33 +218,33 @@ object (self)
203218
| Break _
204219
| Continue _
205220
| Goto _ -> ()
206-
| TryFinally _
221+
| TryFinally _
207222
| TryExcept _ ->
208223
pr_debug [ STR "Errno analysis does not currently support TryFinally or TryExcept "]
209224

210225
method private create_po_instr (context: program_context_int) (i: instr): unit =
211226
match i with
212227
| Set (_, e, loc) -> self#create_po_exp context#add_rhs e loc
213-
| Call (ret, callee, args, loc) ->
228+
| Call (ret, callee, args, loc) ->
214229
begin
215230
self#create_po_exp context#add_ftarget callee loc;
216231
(match ret with
217232
| None -> ()
218233
| Some r -> self#create_po_lval context#add_lhs r loc);
219234
List.iteri (fun i e -> self#create_po_exp (context#add_arg (i+1)) e loc) args;
220235
end
221-
| VarDecl _
236+
| VarDecl _
222237
| Asm _ -> ()
223238

224239
method create_po_exp (context: program_context_int) (e: exp) (loc: location) =
225240
match e with
226-
| Lval (Mem (Lval (Var x, NoOffset)), NoOffset) when errno_aliases#has (snd x) ->
241+
| Lval (Mem (Lval (Var x, NoOffset)), NoOffset) when errno_aliases#has (snd x) ->
227242
self#add_ppo PErrnoWritten loc context;
228243
| Lval (Mem e, _) -> self#create_po_exp context#add_lval#add_mem e loc
229244
| Lval (Var _, _) -> ()
230245
| UnOp (_, e, _) -> self#create_po_exp context#add_unop e loc
231-
| BinOp (_, e1, e2, _) ->
232-
begin
246+
| BinOp (_, e1, e2, _) ->
247+
begin
233248
self#create_po_exp (context#add_binop 1) e1 loc;
234249
self#create_po_exp (context#add_binop 2) e2 loc;
235250
end
@@ -252,7 +267,7 @@ object (self)
252267
| AddrOfLabel _
253268
| SizeOfE _ -> ()
254269

255-
method private create_po_lval context lval loc: unit =
270+
method private create_po_lval context lval loc: unit =
256271
match lval with
257272
| (Var _, _) -> ()
258273
| (Mem e, _) -> self#create_po_exp context#add_mem e loc
@@ -268,7 +283,7 @@ let process_function (fname:string): unit traceresult =
268283
let _ = log_info "Process function %s [%s:%d]" fname __FILE__ __LINE__ in
269284
let fundec = read_function_semantics fname in
270285
let _ = read_proof_files fname fundec.sdecls in
271-
let* errnos = check_errno_pointer_uses_in_block fundec.sdecls fundec.sbody
286+
let* errnos = check_errno_pointer_uses_in_block fundec.sdecls fundec.sbody
272287
|> result_of_option "Can not run errno analysis, found code we can not analyze"
273288
in
274289
let _ = (new po_creator_t fundec errnos)#create_proof_obligations in

0 commit comments

Comments
 (0)