Skip to content

Commit 318fc06

Browse files
committed
Improve control-flow analysis of "noreturn" function calls
- Honor "noreturn" attributes and _Noreturn declarations on calls to function pointers. - Don't crash if a function type is an unknown typedef. (This can happen with local typedefs.) Instead, conservatively assume this function can return.
1 parent 413bd76 commit 318fc06

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

cparser/Cflow.ml

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,18 @@ let rec contains_default s =
204204
| Sdecl dcl -> false
205205
| Sasm _ -> false
206206

207+
(* Extract the attributes of a function type, looking for "noreturn". *)
208+
209+
let rec function_attributes env = function
210+
| TFun(_, _, _, a) -> a
211+
| TPtr(t, _) -> function_attributes env t
212+
| TNamed _ as t ->
213+
begin match unroll env t with
214+
| t' -> function_attributes env t'
215+
| exception Env.Error _ -> []
216+
(* Any error due to local types should be ignored *)
217+
end
218+
| _ -> []
207219

208220
(* This is the main analysis function. Given a C statement [s] it returns
209221
a flow that overapproximates the behavior of [s]. *)
@@ -213,10 +225,12 @@ let rec outcomes env s : flow =
213225
| Sskip ->
214226
normal
215227
| Sdo {edesc = ECall(fn, args)} ->
216-
let returns = find_custom_attributes ["noreturn"; "__noreturn__"]
217-
(attributes_of_type env fn.etyp) = [] in
218-
let std_noreturn = List.exists (is_call_to_fun fn) std_noreturn_functions in
219-
if returns && not std_noreturn then normal else noflow
228+
let attr_noreturn =
229+
find_custom_attributes ["noreturn"; "__noreturn__"]
230+
(function_attributes env fn.etyp)
231+
and std_noreturn =
232+
List.exists (is_call_to_fun fn) std_noreturn_functions in
233+
if attr_noreturn <> [] || std_noreturn then noflow else normal
220234
| Sdo e ->
221235
normal
222236
| Sseq(s1, s2) ->

0 commit comments

Comments
 (0)