[impurity] Refactor and ignore invalidations to constant dereferences

Summary:
- ignore  `ConstantDereference` invalidations since they just represent assignments to constants.
- add `impurity.mli`
- split `extract_impurity` into several sub functions.

Reviewed By: jvillard

Differential Revision: D20335674

fbshipit-source-id: f0fd6b5f4
master
Ezgi Çiçek 5 years ago committed by Facebook Github Bot
parent 83e72b2cbc
commit ddd09b83fd

@ -12,9 +12,6 @@ open PulseDomainInterface
let debug fmt = L.(debug Analysis Verbose fmt) let debug fmt = L.(debug Analysis Verbose fmt)
(* An impurity analysis that relies on pulse to determine how the state
changes *)
let get_matching_dest_addr_opt ~edges_pre ~edges_post : AbstractValue.t list option = let get_matching_dest_addr_opt ~edges_pre ~edges_post : AbstractValue.t list option =
match match
List.fold2 ~init:(Some []) List.fold2 ~init:(Some [])
@ -37,23 +34,19 @@ let add_invalid_and_modified ~check_empty attrs acc =
Attributes.get_written_to attrs Attributes.get_written_to attrs
|> Option.value_map ~default:[] ~f:(fun modified -> [ImpurityDomain.WrittenTo modified]) |> Option.value_map ~default:[] ~f:(fun modified -> [ImpurityDomain.WrittenTo modified])
in in
let res = let invalid_and_modified =
Attributes.get_invalid attrs match Attributes.get_invalid attrs with
|> Option.value_map ~default:modified ~f:(fun invalid -> | None | Some (PulseInvalidation.ConstantDereference _, _) ->
ImpurityDomain.Invalid invalid :: modified ) modified
| Some invalid ->
ImpurityDomain.Invalid invalid :: modified
in in
if check_empty && List.is_empty res then if check_empty && List.is_empty invalid_and_modified then
L.(die InternalError) "Address is modified without being written to or invalidated." L.(die InternalError) "Address is modified without being written to or invalidated."
else res @ acc else invalid_and_modified @ acc
(** Given Pulse summary, extract impurity info, i.e. parameters and global variables that are let add_to_modified var addr pre_heap post acc =
modified by the function and skipped functions. *)
let extract_impurity tenv pdesc pre_post : ImpurityDomain.t =
let pre_heap = (AbductiveDomain.extract_pre pre_post).BaseDomain.heap in
let post = AbductiveDomain.extract_post pre_post in
let post_stack = post.BaseDomain.stack in
let add_to_modified var addr acc =
let rec aux acc ~addr_to_explore ~visited : ImpurityDomain.trace list = let rec aux acc ~addr_to_explore ~visited : ImpurityDomain.trace list =
match addr_to_explore with match addr_to_explore with
| [] -> | [] ->
@ -90,28 +83,39 @@ let extract_impurity tenv pdesc pre_post : ImpurityDomain.t =
acc acc
| hd :: tl -> | hd :: tl ->
ImpurityDomain.ModifiedVarSet.add {var; trace_list= (hd, tl)} acc ImpurityDomain.ModifiedVarSet.add {var; trace_list= (hd, tl)} acc
in
let pname = Procdesc.get_proc_name pdesc in
let modified_params = let get_modified_params pname post_stack pre_heap post formals =
Procdesc.get_formals pdesc List.fold_left formals ~init:ImpurityDomain.ModifiedVarSet.empty ~f:(fun acc (name, typ) ->
|> List.fold_left ~init:ImpurityDomain.ModifiedVarSet.empty ~f:(fun acc (name, typ) ->
let var = Var.of_pvar (Pvar.mk name pname) in let var = Var.of_pvar (Pvar.mk name pname) in
match BaseStack.find_opt var post_stack with match BaseStack.find_opt var post_stack with
| Some (addr, _) when Typ.is_pointer typ -> ( | Some (addr, _) when Typ.is_pointer typ -> (
match BaseMemory.find_opt addr pre_heap with match BaseMemory.find_opt addr pre_heap with
| Some edges_pre -> | Some edges_pre ->
BaseMemory.Edges.fold BaseMemory.Edges.fold
(fun _ (addr, _) acc -> add_to_modified var addr acc) (fun _ (addr, _) acc -> add_to_modified var addr pre_heap post acc)
edges_pre acc edges_pre acc
| None -> | None ->
debug "The address is not materialized in pre-heap." ; debug "The address is not materialized in pre-heap." ;
acc ) acc )
| _ -> | _ ->
acc ) acc )
(** Given Pulse summary, extract impurity info, i.e. parameters and global variables that are
modified by the function and skipped functions. *)
let extract_impurity tenv pdesc pre_post : ImpurityDomain.t =
let pre_heap = (AbductiveDomain.extract_pre pre_post).BaseDomain.heap in
let post = AbductiveDomain.extract_post pre_post in
let post_stack = post.BaseDomain.stack in
let pname = Procdesc.get_proc_name pdesc in
let modified_params =
Procdesc.get_formals pdesc |> get_modified_params pname post_stack pre_heap post
in in
let modified_globals = let modified_globals =
BaseStack.fold BaseStack.fold
(fun var (addr, _) acc -> if Var.is_global var then add_to_modified var addr acc else acc) (fun var (addr, _) acc ->
if Var.is_global var then add_to_modified var addr pre_heap post acc else acc )
post_stack ImpurityDomain.ModifiedVarSet.empty post_stack ImpurityDomain.ModifiedVarSet.empty
in in
let is_modeled_pure pname = let is_modeled_pure pname =

@ -0,0 +1,11 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
val checker : Callbacks.proc_callback_t
(** An impurity analysis that relies on pulse summaries to determine how the state changes *)
Loading…
Cancel
Save