[inferbo] Prepare for several kinds of safety conditions

Reviewed By: jvillard

Differential Revision: D6373063

fbshipit-source-id: ef7cd35
master
Mehdi Bouaziz 7 years ago committed by Facebook Github Bot
parent cb363d8dcb
commit d12371c6c3

@ -541,14 +541,9 @@ module Report = struct
let report_error : Procdesc.t -> PO.ConditionSet.t -> unit = let report_error : Procdesc.t -> PO.ConditionSet.t -> unit =
fun pdesc conds -> fun pdesc cond_set ->
let pname = Procdesc.get_proc_name pdesc in let pname = Procdesc.get_proc_name pdesc in
let report1 cond trace = let report cond trace issue_type =
let alarm = PO.Condition.check cond in
match alarm with
| None ->
()
| Some issue_type ->
let caller_pname, location = let caller_pname, location =
match PO.ConditionTrace.get_cond_trace trace with match PO.ConditionTrace.get_cond_trace trace with
| PO.ConditionTrace.Inter (caller_pname, _, location) -> | PO.ConditionTrace.Inter (caller_pname, _, location) ->
@ -569,7 +564,7 @@ module Report = struct
in in
Reporting.log_error_deprecated pname ~loc:location ~ltr:trace exn Reporting.log_error_deprecated pname ~loc:location ~ltr:trace exn
in in
PO.ConditionSet.iter conds ~f:report1 PO.ConditionSet.check_all ~report cond_set
end end

@ -15,7 +15,7 @@ module ItvPure = Itv.ItvPure
module MF = MarkupFormatter module MF = MarkupFormatter
module ValTraceSet = BufferOverrunTrace.Set module ValTraceSet = BufferOverrunTrace.Set
module Condition = struct module ArrayAccessCondition = struct
type t = {idx: ItvPure.astate; size: ItvPure.astate} [@@deriving compare] type t = {idx: ItvPure.astate; size: ItvPure.astate} [@@deriving compare]
let get_symbols c = ItvPure.get_symbols c.idx @ ItvPure.get_symbols c.size let get_symbols c = ItvPure.get_symbols c.idx @ ItvPure.get_symbols c.size
@ -149,8 +149,8 @@ module Condition = struct
else Some IssueType.buffer_overrun_l3 else Some IssueType.buffer_overrun_l3
let subst : t -> Itv.Bound.t bottom_lifted Itv.SubstMap.t -> t option = let subst : Itv.Bound.t bottom_lifted Itv.SubstMap.t -> t -> t option =
fun c bound_map -> fun bound_map c ->
match (ItvPure.subst c.idx bound_map, ItvPure.subst c.size bound_map) with match (ItvPure.subst c.idx bound_map, ItvPure.subst c.size bound_map) with
| NonBottom idx, NonBottom size -> | NonBottom idx, NonBottom size ->
Some {idx; size} Some {idx; size}
@ -159,6 +159,35 @@ module Condition = struct
end end
module Condition = struct
type t = ArrayAccess of ArrayAccessCondition.t [@@deriving compare]
let make_array_access = Option.map ~f:(fun c -> ArrayAccess c)
let get_symbols = function ArrayAccess c -> ArrayAccessCondition.get_symbols c
let subst bound_map = function
| ArrayAccess c ->
ArrayAccessCondition.subst bound_map c |> make_array_access
let have_similar_bounds c1 c2 =
match (c1, c2) with ArrayAccess c1, ArrayAccess c2 ->
ArrayAccessCondition.have_similar_bounds c1 c2
let xcompare ~lhs ~rhs =
match (lhs, rhs) with ArrayAccess lhs, ArrayAccess rhs ->
ArrayAccessCondition.xcompare ~lhs ~rhs
let pp fmt = function ArrayAccess c -> ArrayAccessCondition.pp fmt c
let pp_description fmt = function ArrayAccess c -> ArrayAccessCondition.pp_description fmt c
let check = function ArrayAccess c -> ArrayAccessCondition.check c
end
module ConditionTrace = struct module ConditionTrace = struct
type cond_trace = type cond_trace =
| Intra of Typ.Procname.t | Intra of Typ.Procname.t
@ -238,14 +267,14 @@ module ConditionSet = struct
let try_merge ~existing ~new_ = let try_merge ~existing ~new_ =
(* we don't want to remove issues that would end up in a higher bucket,
e.g. [a, b] < [c, d] is subsumed by [a, +oo] < [c, d] but the latter is less precise *)
if Condition.have_similar_bounds existing.cond new_.cond then if Condition.have_similar_bounds existing.cond new_.cond then
match Condition.xcompare ~lhs:existing.cond ~rhs:new_.cond with match Condition.xcompare ~lhs:existing.cond ~rhs:new_.cond with
| `Equal -> | `Equal ->
(* keep the first one in the code *) (* keep the first one in the code *)
if compare_by_location existing new_ <= 0 then `DoNotAddAndStop if compare_by_location existing new_ <= 0 then `DoNotAddAndStop
else `RemoveExistingAndContinue else `RemoveExistingAndContinue
(* we don't want to remove issues that would end up in a higher bucket,
e.g. [a, b] < [c, d] is subsumed by [a, +oo] < [c, d] but the latter is less precise *)
| `LeftSubsumesRight -> | `LeftSubsumesRight ->
`DoNotAddAndStop `DoNotAddAndStop
| `RightSubsumesLeft -> | `RightSubsumesLeft ->
@ -274,7 +303,7 @@ module ConditionSet = struct
let join condset1 condset2 = List.fold_left ~f:add_one condset1 ~init:condset2 let join condset1 condset2 = List.fold_left ~f:add_one condset1 ~init:condset2
let add_bo_safety pname location id ~idx ~size val_traces condset = let add_bo_safety pname location id ~idx ~size val_traces condset =
match Condition.make ~idx ~size with match ArrayAccessCondition.make ~idx ~size |> Condition.make_array_access with
| None -> | None ->
condset condset
| Some cond -> | Some cond ->
@ -293,7 +322,7 @@ module ConditionSet = struct
| [] -> | [] ->
add_one condset cwt add_one condset cwt
| symbols -> | symbols ->
match Condition.subst cwt.cond bound_map with match Condition.subst bound_map cwt.cond with
| None -> | None ->
condset condset
| Some cond -> | Some cond ->
@ -315,7 +344,14 @@ module ConditionSet = struct
List.fold condset ~f:subst_add_cwt ~init:[] List.fold condset ~f:subst_add_cwt ~init:[]
let iter ~f condset = List.iter condset ~f:(fun cwt -> f cwt.cond cwt.trace) let check_all ~report condset =
List.iter condset ~f:(fun cwt ->
match Condition.check cwt.cond with
| None ->
()
| Some issue_type ->
report cwt.cond cwt.trace issue_type )
let pp_cwt fmt cwt = F.fprintf fmt "%a %a" Condition.pp cwt.cond ConditionTrace.pp cwt.trace let pp_cwt fmt cwt = F.fprintf fmt "%a %a" Condition.pp cwt.cond ConditionTrace.pp cwt.trace

Loading…
Cancel
Save