[pulse] more aggressive join

Summary:
Do the intersection of the heap and stack domains, and the union of the
invalid location sets. This forgets invalid locations that appear only
in one heap, unfortunately. We can start with this and improve later.

Reviewed By: mbouaziz

Differential Revision: D10445825

fbshipit-source-id: cc24460af
master
Jules Villard 6 years ago committed by Facebook Github Bot
parent 6d9943f2aa
commit ad98ffa22b

@ -47,20 +47,40 @@ module AbstractLocationDomain : AbstractDomain.S with type astate = AbstractLoca
let pp = AbstractLocation.pp let pp = AbstractLocation.pp
end end
module MemoryKey = struct module Access = struct
type t = AbstractLocation.t * AccessPath.access [@@deriving compare] type t = AccessPath.access [@@deriving compare]
let pp f k = Pp.pair ~fst:AbstractLocation.pp ~snd:AccessPath.pp_access f k let pp = AccessPath.pp_access
end end
module MemoryDomain = AbstractDomain.Map (MemoryKey) (AbstractLocationDomain) module MemoryEdges = AbstractDomain.InvertedMap (Access) (AbstractLocationDomain)
module AliasingDomain = AbstractDomain.Map (Var) (AbstractLocationDomain)
module MemoryDomain = struct
include AbstractDomain.InvertedMap (AbstractLocation) (MemoryEdges)
let add_edge loc_src access loc_end memory =
let edges =
match find_opt loc_src memory with Some edges -> edges | None -> MemoryEdges.empty
in
add loc_src (MemoryEdges.add access loc_end edges) memory
let find_edge_opt loc access memory =
let open Option.Monad_infix in
find_opt loc memory >>= MemoryEdges.find_opt access
end
module AliasingDomain = AbstractDomain.InvertedMap (Var) (AbstractLocationDomain)
module AbstractLocationsDomain = AbstractDomain.FiniteSet (AbstractLocation) module AbstractLocationsDomain = AbstractDomain.FiniteSet (AbstractLocation)
module InvalidLocationsDomain = AbstractLocationsDomain module InvalidLocationsDomain = AbstractLocationsDomain
type t = type t =
{heap: MemoryDomain.astate; stack: AliasingDomain.astate; invalids: InvalidLocationsDomain.astate} {heap: MemoryDomain.astate; stack: AliasingDomain.astate; invalids: InvalidLocationsDomain.astate}
let initial =
{heap= MemoryDomain.empty; stack= AliasingDomain.empty; invalids= AbstractLocationsDomain.empty}
module Domain : AbstractDomain.S with type astate = t = struct module Domain : AbstractDomain.S with type astate = t = struct
type astate = t type astate = t
@ -107,10 +127,6 @@ end
include Domain include Domain
let initial =
{heap= MemoryDomain.empty; stack= AliasingDomain.empty; invalids= AbstractLocationsDomain.empty}
module Diagnostic = struct module Diagnostic = struct
(* TODO: more structured error type so that we can actually report something informative about (* TODO: more structured error type so that we can actually report something informative about
the variables being accessed along with a trace *) the variables being accessed along with a trace *)
@ -140,15 +156,15 @@ let rec walk ~overwrite_last loc path astate =
| [a], Some new_loc -> | [a], Some new_loc ->
check_loc_access loc astate check_loc_access loc astate
>>| fun astate -> >>| fun astate ->
let heap = MemoryDomain.add (loc, a) new_loc astate.heap in let heap = MemoryDomain.add_edge loc a new_loc astate.heap in
({astate with heap}, new_loc) ({astate with heap}, new_loc)
| a :: path, _ -> ( | a :: path, _ -> (
check_loc_access loc astate check_loc_access loc astate
>>= fun astate -> >>= fun astate ->
match MemoryDomain.find_opt (loc, a) astate.heap with match MemoryDomain.find_edge_opt loc a astate.heap with
| None -> | None ->
let loc' = AbstractLocation.mk_fresh () in let loc' = AbstractLocation.mk_fresh () in
let heap = MemoryDomain.add (loc, a) loc' astate.heap in let heap = MemoryDomain.add_edge loc a loc' astate.heap in
let astate = {astate with heap} in let astate = {astate with heap} in
walk ~overwrite_last loc' path astate walk ~overwrite_last loc' path astate
| Some loc' -> | Some loc' ->

@ -14,8 +14,8 @@ module AbstractLocation : sig
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
end end
module MemoryKey : sig module Access : sig
type t = AbstractLocation.t * AccessPath.access [@@deriving compare] type t = AccessPath.access [@@deriving compare]
val pp : F.formatter -> t -> unit val pp : F.formatter -> t -> unit
end end
@ -24,9 +24,11 @@ module AbstractLocationDomain : AbstractDomain.S with type astate = AbstractLoca
module AbstractLocationsDomain : module type of AbstractDomain.FiniteSet (AbstractLocation) module AbstractLocationsDomain : module type of AbstractDomain.FiniteSet (AbstractLocation)
module MemoryDomain : module type of AbstractDomain.Map (MemoryKey) (AbstractLocationDomain) module MemoryEdges : module type of AbstractDomain.InvertedMap (Access) (AbstractLocationDomain)
module AliasingDomain : module type of AbstractDomain.Map (Var) (AbstractLocationDomain) module MemoryDomain : module type of AbstractDomain.InvertedMap (AbstractLocation) (MemoryEdges)
module AliasingDomain : module type of AbstractDomain.InvertedMap (Var) (AbstractLocationDomain)
module InvalidLocationsDomain : module type of AbstractLocationsDomain module InvalidLocationsDomain : module type of AbstractLocationsDomain

@ -1,6 +1,3 @@
codetoanalyze/cpp/ownership/basics.cpp, multiple_invalidations_loop_bad, 3, USE_AFTER_LIFETIME, no_bucket, ERROR, []
codetoanalyze/cpp/ownership/basics.cpp, multiple_invalidations_loop_bad, 5, USE_AFTER_LIFETIME, no_bucket, ERROR, []
codetoanalyze/cpp/ownership/basics.cpp, multiple_invalidations_loop_bad, 8, USE_AFTER_LIFETIME, no_bucket, ERROR, []
codetoanalyze/cpp/ownership/returns.cpp, returns::return_deleted_bad, 4, USE_AFTER_LIFETIME, no_bucket, ERROR, [] codetoanalyze/cpp/ownership/returns.cpp, returns::return_deleted_bad, 4, USE_AFTER_LIFETIME, no_bucket, ERROR, []
codetoanalyze/cpp/ownership/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_LIFETIME, no_bucket, ERROR, [] codetoanalyze/cpp/ownership/use_after_delete.cpp, delete_in_branch_bad, 5, USE_AFTER_LIFETIME, no_bucket, ERROR, []
codetoanalyze/cpp/ownership/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_LIFETIME, no_bucket, ERROR, [] codetoanalyze/cpp/ownership/use_after_delete.cpp, delete_in_loop_bad, 3, USE_AFTER_LIFETIME, no_bucket, ERROR, []

Loading…
Cancel
Save