Reviewed By: sblackshear Differential Revision: D3900838 fbshipit-source-id: bb58b20master
parent
fbfece20af
commit
419f2e0bdf
@ -0,0 +1,104 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2016 - 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.
|
||||||
|
*)
|
||||||
|
|
||||||
|
(** I want to use various powersets instead of just variables like Var.Set
|
||||||
|
For example to track the analogues of attributes
|
||||||
|
I will do this running forwards later, but backwards for now.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open! Utils
|
||||||
|
|
||||||
|
module F = Format
|
||||||
|
module L = Logging
|
||||||
|
|
||||||
|
module PPstring = PrettyPrintable.MakePPSet(struct
|
||||||
|
type nonrec t = string
|
||||||
|
let compare = string_compare
|
||||||
|
let pp_element fmt s = F.fprintf fmt "%s" s
|
||||||
|
end)
|
||||||
|
|
||||||
|
module PPrawpath = PrettyPrintable.MakePPSet(struct
|
||||||
|
type nonrec t = AccessPath.raw
|
||||||
|
let compare = AccessPath.raw_compare
|
||||||
|
let pp_element = AccessPath.pp_raw
|
||||||
|
end)
|
||||||
|
|
||||||
|
module LocksDomain = AbstractDomain.FiniteSet(PPstring)
|
||||||
|
|
||||||
|
module PathDomain = AbstractDomain.FiniteSet(PPrawpath)
|
||||||
|
|
||||||
|
module ReadWriteDomain = AbstractDomain.Pair (PathDomain) (PathDomain)
|
||||||
|
|
||||||
|
module CombinedDomain = AbstractDomain.Pair (LocksDomain) (ReadWriteDomain)
|
||||||
|
(* a typical element is (){locked}, {vars and fields}) *)
|
||||||
|
|
||||||
|
module TransferFunctions (CFG : ProcCfg.S) = struct
|
||||||
|
module CFG = CFG
|
||||||
|
module Domain = CombinedDomain
|
||||||
|
type extras = ProcData.no_extras
|
||||||
|
|
||||||
|
let is_lock_procedure pn = Procname.equal pn ModelBuiltins.__set_locked_attribute
|
||||||
|
|
||||||
|
let is_unlock_procedure pn = Procname.equal pn ModelBuiltins.__delete_locked_attribute
|
||||||
|
|
||||||
|
let add_path_to_state exp typ pathdomainstate =
|
||||||
|
match AccessPath.of_exp exp typ ~f_resolve_id:(fun _ -> None) with
|
||||||
|
| Some rawpath -> PathDomain.add rawpath pathdomainstate
|
||||||
|
| None -> pathdomainstate
|
||||||
|
|
||||||
|
|
||||||
|
let exec_instr ((lockstate,(readstate,writestate)) as astate) _ _ = function
|
||||||
|
| Sil.Call (_, Exp.Const (Const.Cfun pn), _, _, _) ->
|
||||||
|
if is_lock_procedure pn
|
||||||
|
then
|
||||||
|
((LocksDomain.add "locked" lockstate), (readstate,writestate))
|
||||||
|
else if is_unlock_procedure pn
|
||||||
|
then
|
||||||
|
((LocksDomain.remove "locked" lockstate) , (readstate,writestate))
|
||||||
|
else
|
||||||
|
astate
|
||||||
|
|
||||||
|
| Sil.Store ((Exp.Lfield ( _, _, typ) as lhsfield) , _, _, _) ->
|
||||||
|
if LocksDomain.is_empty lockstate then (* abstracts no lock being held*)
|
||||||
|
(lockstate, (readstate, add_path_to_state lhsfield typ writestate))
|
||||||
|
else astate
|
||||||
|
|
||||||
|
(* Note: it appears that the third arg of Store is never an Lfield in the targets of,
|
||||||
|
our translations, which is why we have not covered that case. *)
|
||||||
|
| Sil.Store (_, _, Exp.Lfield _, _) ->
|
||||||
|
failwith "Unexpected store instruction with rhs field"
|
||||||
|
|
||||||
|
| Sil.Load (_, (Exp.Lfield ( _, _, typ) as rhsfield) , _, _) ->
|
||||||
|
if LocksDomain.is_empty lockstate then (* abstracts no lock being held*)
|
||||||
|
(lockstate, (add_path_to_state rhsfield typ readstate, writestate))
|
||||||
|
else astate
|
||||||
|
|
||||||
|
| _ ->
|
||||||
|
astate
|
||||||
|
end
|
||||||
|
|
||||||
|
module Analyzer =
|
||||||
|
AbstractInterpreter.Make
|
||||||
|
(ProcCfg.Normal)
|
||||||
|
(Scheduler.ReversePostorder)
|
||||||
|
(TransferFunctions)
|
||||||
|
|
||||||
|
let checker { Callbacks.proc_desc; tenv; } =
|
||||||
|
match Analyzer.compute_post (ProcData.make_default proc_desc tenv) with
|
||||||
|
| Some post -> (* I am printing to commandline and out to cater to javac and buck*)
|
||||||
|
((L.stdout "\n Procedure: %s@ "
|
||||||
|
(Procname.to_string (Cfg.Procdesc.get_proc_name proc_desc) )
|
||||||
|
);
|
||||||
|
L.stdout "\n POST: %a\n" CombinedDomain.pp post;
|
||||||
|
(L.out "\n Procedure: %s@ "
|
||||||
|
(Procname.to_string (Cfg.Procdesc.get_proc_name proc_desc) )
|
||||||
|
);
|
||||||
|
L.out "\n POST: %a\n" CombinedDomain.pp post
|
||||||
|
)
|
||||||
|
| None -> ()
|
Loading…
Reference in new issue