fix possible infinite loop in get_fld_typ_path

Reviewed By: cristianoc

Differential Revision: D2798766

fb-gh-sync-id: ff0f582
master
Sam Blackshear 9 years ago committed by facebook-github-bot-5
parent 51f494f542
commit 43ee904a1f

@ -625,7 +625,10 @@ let report_context_leaks pname sigma tenv =
IList.iter IList.iter
(fun (context_exp, typ) -> (fun (context_exp, typ) ->
if Sil.ExpSet.mem context_exp reachable_exps then if Sil.ExpSet.mem context_exp reachable_exps then
let leak_path = Prop.get_fld_typ_path fld_exps context_exp reachable_hpreds in let leak_path =
match Prop.get_fld_typ_path_opt fld_exps context_exp reachable_hpreds with
| Some path -> path
| None -> assert false in (* a path must exist in order for a leak to be reported *)
let err_desc = Errdesc.explain_context_leak pname typ fld_name leak_path in let err_desc = Errdesc.explain_context_leak pname typ fld_name leak_path in
let exn = Exceptions.Context_leak let exn = Exceptions.Context_leak
(err_desc, try assert false with Assert_failure x -> x) in (err_desc, try assert false with Assert_failure x -> x) in

@ -1569,34 +1569,38 @@ let compute_reachable_hpreds sigma exps =
else compute_reachable_hpreds_rec sigma (reach', exps') in else compute_reachable_hpreds_rec sigma (reach', exps') in
compute_reachable_hpreds_rec sigma (Sil.HpredSet.empty, exps) compute_reachable_hpreds_rec sigma (Sil.HpredSet.empty, exps)
(** produce a (fieldname, typ) from one of the [src_exps] to [snk_exp] using [reachable_hpreds] *) (** if possible, produce a (fieldname, typ) path from one of the [src_exps] to [snk_exp] using
let rec get_fld_typ_path src_exps snk_exp reachable_hpreds = [reachable_hpreds]. *)
let get_fld_typ_path_opt src_exps snk_exp_ reachable_hpreds_ =
let strexp_matches target_exp = function let strexp_matches target_exp = function
| (_, Sil.Eexp (e, _)) -> Sil.exp_equal target_exp e | (_, Sil.Eexp (e, _)) -> Sil.exp_equal target_exp e
| _ -> false in | _ -> false in
let (snk_exp, path) = let extend_path hpred (snk_exp, path, reachable_hpreds) = match hpred with
Sil.HpredSet.fold
(fun hpred (snk_exp, path) -> match hpred with
| Sil.Hpointsto (lhs, Sil.Estruct (flds, inst), Sil.Sizeof (typ, _)) -> | Sil.Hpointsto (lhs, Sil.Estruct (flds, inst), Sil.Sizeof (typ, _)) ->
(match (try
IList.fold_left let fld, _ = IList.find (fun fld -> strexp_matches snk_exp fld) flds in
(fun acc fld -> if strexp_matches snk_exp fld then Some fld else acc) let reachable_hpreds' = Sil.HpredSet.remove hpred reachable_hpreds in
None (lhs, (Some fld, typ) :: path, reachable_hpreds')
flds with with Not_found -> (snk_exp, path, reachable_hpreds))
| Some (fld, _) -> (lhs, (Some fld, typ) :: path)
| None -> (snk_exp, path))
| Sil.Hpointsto (lhs, Sil.Earray (_, elems, _), Sil.Sizeof (typ, _)) -> | Sil.Hpointsto (lhs, Sil.Earray (_, elems, _), Sil.Sizeof (typ, _)) ->
if IList.exists (fun pair -> strexp_matches snk_exp pair) elems if IList.exists (fun pair -> strexp_matches snk_exp pair) elems
then then
let reachable_hpreds' = Sil.HpredSet.remove hpred reachable_hpreds in
(* None means "no field name" ~=~ nameless array index *) (* None means "no field name" ~=~ nameless array index *)
(lhs, (None, typ) :: path) (lhs, (None, typ) :: path, reachable_hpreds')
else (snk_exp, path) else (snk_exp, path, reachable_hpreds)
| _ -> (snk_exp, path)) | _ -> (snk_exp, path, reachable_hpreds) in
reachable_hpreds (* terminates because [reachable_hpreds] is shrinking on each recursive call *)
(snk_exp, []) in let rec get_fld_typ_path snk_exp path reachable_hpreds =
if Sil.ExpSet.mem snk_exp src_exps then path let (snk_exp', path', reachable_hpreds') =
else get_fld_typ_path src_exps snk_exp reachable_hpreds Sil.HpredSet.fold extend_path reachable_hpreds (snk_exp, path, reachable_hpreds) in
if Sil.ExpSet.mem snk_exp' src_exps
then Some path'
else
if Sil.HpredSet.cardinal reachable_hpreds' >= Sil.HpredSet.cardinal reachable_hpreds
then None (* can't find a path from [src_exps] to [snk_exp] *)
else get_fld_typ_path snk_exp' path' reachable_hpreds' in
get_fld_typ_path snk_exp_ [] reachable_hpreds_
(** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *) (** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *)
let compute_reachable_atoms pi exps = let compute_reachable_atoms pi exps =

@ -482,9 +482,11 @@ val hpred_get_targets : Sil.hpred -> Sil.ExpSet.t
[exps] *) [exps] *)
val compute_reachable_hpreds : hpred list -> Sil.ExpSet.t -> Sil.HpredSet.t * Sil.ExpSet.t val compute_reachable_hpreds : hpred list -> Sil.ExpSet.t -> Sil.HpredSet.t * Sil.ExpSet.t
(** produce a (fieldname, typ) from one of the [src_exps] to [snk_exp] using [reachable_hpreds] *)
val get_fld_typ_path : Sil.ExpSet.t -> Sil.exp -> Sil.HpredSet.t -> (** if possible, produce a (fieldname, typ) path from one of the [src_exps] to [snk_exp] using
(Ident.fieldname option * Sil.typ) list [reachable_hpreds]. *)
val get_fld_typ_path_opt : Sil.ExpSet.t -> Sil.exp -> Sil.HpredSet.t ->
(Ident.fieldname option * Sil.typ) list option
(** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *) (** filter [pi] by removing the pure atoms that do not contain an expression in [exps] *)
val compute_reachable_atoms : Sil.atom list -> Sil.ExpSet.t -> Sil.atom list val compute_reachable_atoms : Sil.atom list -> Sil.ExpSet.t -> Sil.atom list

Loading…
Cancel
Save