Reviewed By: peterogithub Differential Revision: D4452608 fbshipit-source-id: 1761045master
parent
d25a3edbd7
commit
851a4da7e0
@ -0,0 +1,79 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2017 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open! IStd
|
||||||
|
|
||||||
|
module F = Format
|
||||||
|
|
||||||
|
module RawAccessPath : sig
|
||||||
|
type t = AccessPath.raw
|
||||||
|
val compare : t -> t -> int
|
||||||
|
val pp : Format.formatter -> t -> unit
|
||||||
|
val pp_element : Format.formatter -> t -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
module RawAccessPathSet : PrettyPrintable.PPSet with type elt = RawAccessPath.t
|
||||||
|
|
||||||
|
module OwnershipDomain : module type of AbstractDomain.InvertedSet (RawAccessPathSet)
|
||||||
|
|
||||||
|
module TraceElem : TraceElem.S with module Kind = RawAccessPath
|
||||||
|
|
||||||
|
(** A bool that is true if a lock is definitely held. Note that this is unsound because it assumes
|
||||||
|
the existence of one global lock. In the case that a lock is held on the access to a variable,
|
||||||
|
but the lock held is the wrong one, we will erroneously say that the access is thread-safe.
|
||||||
|
However, this coarse abstraction saves us from the complexity of tracking which locks are held
|
||||||
|
and which memory locations correspond to the same lock. *)
|
||||||
|
module LocksDomain : AbstractDomain.S with type astate = bool
|
||||||
|
|
||||||
|
module PathDomain : module type of SinkTrace.Make(TraceElem)
|
||||||
|
|
||||||
|
module IntMap : PrettyPrintable.PPMap with type key = int
|
||||||
|
|
||||||
|
module ConditionalWritesDomain : module type of (AbstractDomain.Map (IntMap) (PathDomain))
|
||||||
|
|
||||||
|
(** the primary role of this domain is tracking *conditional* and *unconditional* writes.
|
||||||
|
conditional writes are writes that are rooted in a formal of the current procedure, and they
|
||||||
|
are safe only if the actual bound to that formal is owned at the call site (as in the foo
|
||||||
|
example below). Unconditional writes are rooted in a local, and they are only safe if a lock is
|
||||||
|
held in the caller.
|
||||||
|
To demonstrate what conditional writes buy us, consider the following example:
|
||||||
|
|
||||||
|
foo() {
|
||||||
|
Object local = new Object();
|
||||||
|
iWriteToAField(local);
|
||||||
|
}
|
||||||
|
|
||||||
|
We don't want to warn on this example because the object pointed to by local is owned by the
|
||||||
|
caller foo, then ownership is transferred to the callee iWriteToAField. *)
|
||||||
|
type astate =
|
||||||
|
{
|
||||||
|
locks : LocksDomain.astate;
|
||||||
|
(** boolean that is true if a lock must currently be held *)
|
||||||
|
reads : PathDomain.astate;
|
||||||
|
(** access paths read outside of synchronization *)
|
||||||
|
conditional_writes : ConditionalWritesDomain.astate;
|
||||||
|
(** map of (formal index) -> set of access paths rooted in the formal index that are read
|
||||||
|
outside of synrchonization if the formal is not owned by the caller *)
|
||||||
|
unconditional_writes : PathDomain.astate;
|
||||||
|
(** access paths written outside of synchronization *)
|
||||||
|
id_map : IdAccessPathMapDomain.astate;
|
||||||
|
(** map used to decompile temporary variables into access paths *)
|
||||||
|
owned : OwnershipDomain.astate;
|
||||||
|
(** access paths that must be owned by the current function *)
|
||||||
|
}
|
||||||
|
|
||||||
|
(** same as astate, but without [id_map]/[owned] (since they are local) *)
|
||||||
|
type summary =
|
||||||
|
LocksDomain.astate * PathDomain.astate * ConditionalWritesDomain.astate * PathDomain.astate
|
||||||
|
|
||||||
|
include AbstractDomain.WithBottom with type astate := astate
|
||||||
|
|
||||||
|
val make_access : RawAccessPath.t -> Location.t -> TraceElem.t
|
||||||
|
|
||||||
|
val pp_summary : F.formatter -> summary -> unit
|
Loading…
Reference in new issue