@@ -564,18 +564,18 @@ struct
564564
565565 (* From a list of values, presumably arguments to a function, simply extract
566566 * the pointer arguments. *)
567- let get_ptrs (vals : value list ): address list =
567+ let get_ptrs (vals : value list ): address =
568568 let f acc (x :value ) = match x with
569569 | Address adrs when AD. is_top adrs ->
570570 M. info ~category: Unsound " Unknown address given as function argument" ; acc
571571 | Address adrs when AD. to_var_may adrs = [] -> acc
572572 | Address adrs ->
573573 let typ = AD. type_of adrs in
574- if isFunctionType typ then acc else adrs :: acc
574+ if isFunctionType typ then acc else AD. join adrs acc
575575 | Top -> M. info ~category: Unsound " Unknown value type given as function argument" ; acc
576576 | _ -> acc
577577 in
578- List. fold_left f [] vals
578+ List. fold_left f ( AD. empty () ) vals
579579
580580 let rec reachable_from_value ask (value : value ) (t : typ ) (description : string ) =
581581 let empty = AD. empty () in
@@ -605,37 +605,35 @@ struct
605605 (* Get the list of addresses accessable immediately from a given address, thus
606606 * all pointers within a structure should be considered, but we don't follow
607607 * pointers. We return a flattend representation, thus simply an address (set). *)
608- let reachable_from_address ~man st (adr : address ): address =
609- if M. tracing then M. tracei " reachability" " Checking for %a" AD . pretty adr ;
610- let res = reachable_from_value (Analyses. ask_of_man man) (get ~man st adr None ) (AD . type_of adr ) (AD . show adr ) in
608+ let reachable_from_addr ~man st (addr : Addr.t ): address =
609+ if M. tracing then M. tracei " reachability" " Checking for %a" Addr . pretty addr ;
610+ let res = reachable_from_value (Analyses. ask_of_man man) (get_addr ~man st addr None ) (Addr . type_of addr ) (Addr . show addr ) in
611611 if M. tracing then M. traceu " reachability" " Reachable addresses: %a" AD. pretty res;
612612 res
613613
614614 (* The code for getting the variables reachable from the list of parameters.
615615 * This section is very confusing, because I use the same construct, a set of
616616 * addresses, as both AD elements abstracting individual (ambiguous) addresses
617617 * and the workset of visited addresses. *)
618- let reachable_vars ~man (st : store ) (args : address list ): address list =
619- if M. tracing then M. traceli " reachability" " Checking reachable arguments from [%a] !" (d_list " , " AD. pretty) args;
618+ let reachable_vars ~man (st : store ) (args : address ): address =
619+ if M. tracing then M. traceli " reachability" " Checking reachable arguments from %a !" AD. pretty args;
620620 let empty = AD. empty () in
621621 (* We begin looking at the parameters: *)
622- let argset = List. fold_left (AD. join) empty args in
623- let workset = ref argset in
622+ let workset = ref args in
624623 (* And we keep a set of already visited variables *)
625624 let visited = ref empty in
626625 while not (AD. is_empty ! workset) do
627626 visited := AD. union ! visited ! workset;
628627 (* ok, let's visit all the variables in the workset and collect the new variables *)
629628 let visit_and_collect var (acc : address ): address =
630- let var = AD. singleton var in (* Very bad hack! Pathetic really! *)
631- AD. union (reachable_from_address ~man st var) acc in
629+ AD. union (reachable_from_addr ~man st var) acc in
632630 let collected = AD. fold visit_and_collect ! workset empty in
633631 (* And here we remove the already visited variables *)
634632 workset := AD. diff collected ! visited
635633 done ;
636634 (* Return the list of elements that have been visited. *)
637635 if M. tracing then M. traceu " reachability" " All reachable vars: %a" AD. pretty ! visited;
638- List. map AD. singleton ( AD. elements ! visited)
636+ ! visited
639637
640638 let reachable_vars ~man st args = Timing. wrap " reachability" (reachable_vars ~man st) args
641639
@@ -1568,12 +1566,11 @@ struct
15681566 | Bot -> Queries.Result. bot q (* TODO: remove *)
15691567 | Address a ->
15701568 let a' = AD. remove Addr. UnknownPtr a in (* run reachable_vars without unknown just to be safe: TODO why? *)
1571- let addrs = reachable_vars ~man man.local [a'] in
1572- let addrs' = List. fold_left (AD. join) (AD. empty () ) addrs in
1569+ let addrs = reachable_vars ~man man.local a' in
15731570 if AD. may_be_unknown a then
1574- AD. add UnknownPtr addrs' (* add unknown back *)
1571+ AD. add UnknownPtr addrs (* add unknown back *)
15751572 else
1576- addrs'
1573+ addrs
15771574 | Int i ->
15781575 begin match Cilfacade. typeOf e with
15791576 | t when Cil. isPointerType t -> AD. of_int i (* integer used as pointer *)
@@ -1808,14 +1805,17 @@ struct
18081805 let set_var ~(man : _ man ) ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override (st : store ) (x : Cil.varinfo ) (lval_type : Cil.typ ) (value : value ): store =
18091806 set_mval ~man ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override st (x, `NoOffset ) lval_type value
18101807
1808+ let set_addr ~(man : _ man ) ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override (st : store ) (x : Addr.t ) (lval_type : Cil.typ ) (value : value ): store =
1809+ Option. map_default (fun x -> set_mval ~man ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override st x lval_type value) st (Addr. to_mval x)
1810+
18111811 (* * [set st addr val] returns a state where [addr] is set to [val]
18121812 * it is always ok to put None for lval_raw and rval_raw, this amounts to not using/maintaining
18131813 * precise information about arrays. *)
18141814 let set ~(man : _ man ) ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override (st : store ) (lval : AD.t ) (lval_type : Cil.typ ) (value : value ) : store =
18151815 let lval_raw = (Option. map (fun x -> Lval x) lval_raw) in
18161816 if M. tracing then M. tracel " set" " lval: %a\n value: %a\n state: %a" AD. pretty lval VD. pretty value CPA. pretty st.cpa;
18171817 let update_one x store =
1818- Option. map_default ( fun x -> set_mval ~man ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override store x lval_type value) store ( Addr. to_mval x)
1818+ set_addr ~man ?invariant ?blob_destructive ?lval_raw ?rval_raw ?t_override store x lval_type value
18191819 in try
18201820 (* We start from the current state and an empty list of global deltas,
18211821 * and we assign to all the different possible places: *)
@@ -2100,53 +2100,51 @@ struct
21002100 (* * From a list of expressions, collect a list of addresses that they might point to, or contain pointers to. *)
21012101 let collect_funargs ~man ?(warn =false ) (st :store ) (exps : exp list ) =
21022102 let ask = Analyses. ask_of_man man in
2103- let do_exp e =
2103+ let do_exp acc e =
21042104 let immediately_reachable = reachable_from_value ask (eval_rv ~man st e) (Cilfacade. typeOf e) (CilType.Exp. show e) in
2105- reachable_vars ~man st [ immediately_reachable]
2105+ AD. join acc ( reachable_vars ~man st immediately_reachable)
21062106 in
2107- List. concat_map do_exp exps
2107+ List. fold_left do_exp ( AD. empty () ) exps
21082108
21092109 let collect_invalidate ~deep ~man ?(warn =false ) (st :store ) (exps : exp list ) =
21102110 if deep then
21112111 collect_funargs ~man ~warn st exps
21122112 else (
2113- let mpt e = match eval_rv_address ~man st e with
2114- | Address a -> AD. remove NullPtr a
2115- | _ -> AD. empty ()
2113+ let mpt acc e = match eval_rv_address ~man st e with
2114+ | Address a -> AD. join acc ( AD. remove NullPtr a)
2115+ | _ -> acc
21162116 in
2117- List. map mpt exps
2117+ List. fold_left mpt ( AD. empty () ) exps
21182118 )
21192119
21202120 let invalidate ~(must : bool ) ?(deep =true ) ~man (st :store ) (exps : exp list ): store =
21212121 if M. tracing && exps <> [] then M. tracel " invalidate" " Will invalidate expressions [%a]" (d_list " , " d_plainexp) exps;
21222122 if exps <> [] then M. info ~category: Imprecise " Invalidating expressions: %a" (d_list " , " d_exp) exps;
21232123 (* To invalidate a single address, we create a pair with its corresponding
21242124 * top value. *)
2125- let invalidate_address st a =
2126- let t = try AD . type_of a with Not_found -> voidType in (* TODO: why is this called with empty a to begin with? *)
2127- let v = get ~man st a None in (* None here is ok, just causes us to be a bit less precise *)
2125+ let invalidate_addr ( a : Addr.t ) =
2126+ let t = Addr . type_of a in
2127+ let v = get_addr ~man st a None in (* None here is ok, just causes us to be a bit less precise *)
21282128 let nv = VD. invalidate_value (Queries. to_value_domain_ask (Analyses. ask_of_man man)) t v in
21292129 (a, t, nv)
21302130 in
2131- (* We define the function that invalidates all the values that an address
2132- * expression e may point to *)
2133- let invalidate_exp exps =
2131+ let invalids =
21342132 let args = collect_invalidate ~deep ~man ~warn: true st exps in
2135- List. map (invalidate_address st) args
2133+ let args = AD. elements args in (* split all address sets up because each address of different type (and with different current value) should get a different invalidated value *)
2134+ List. map invalidate_addr args
21362135 in
2137- let invalids = invalidate_exp exps in
21382136 let is_fav_addr x =
2139- List . exists BaseUtil. is_excluded_from_invalidation (AD . to_var_may x)
2137+ GobOption . exists BaseUtil. is_excluded_from_invalidation (Addr . to_var_may x)
21402138 in
21412139 let invalids' = List. filter (fun (x ,_ ,_ ) -> not (is_fav_addr x)) invalids in
21422140 if M. tracing && exps <> [] then (
21432141 let addrs = List. map (Tuple3. first) invalids' in
21442142 let vs = List. map (Tuple3. third) invalids' in
2145- M. tracel " invalidate" " Setting addresses [%a] to values [%a]" (d_list " , " AD . pretty) addrs (d_list " , " VD. pretty) vs
2143+ M. tracel " invalidate" " Setting addresses [%a] to values [%a]" (d_list " , " Addr . pretty) addrs (d_list " , " VD. pretty) vs
21462144 );
21472145 (* copied from set_many *)
2148- let f (acc : store ) ((lval :AD .t ),(typ :Cil.typ ),(value :value )): store =
2149- let acc' = set ~man acc lval typ value in
2146+ let f (acc : store ) ((lval :Addr .t ),(typ :Cil.typ ),(value :value )): store =
2147+ let acc' = set_addr ~man acc lval typ value in
21502148 if must then
21512149 acc'
21522150 else
@@ -2178,7 +2176,7 @@ struct
21782176 add_to_array_map fundec pa;
21792177 let new_cpa = CPA. add_list pa st'.cpa in
21802178 (* List of reachable variables *)
2181- let reachable = List. concat_map AD. to_var_may (reachable_vars ~man st (get_ptrs vals)) in
2179+ let reachable = AD. to_var_may (reachable_vars ~man st (get_ptrs vals)) in
21822180 let reachable = List. filter (fun v -> CPA. mem v st.cpa) reachable in
21832181 let new_cpa = CPA. add_list_fun reachable (fun v -> CPA. find v st.cpa) new_cpa in
21842182
@@ -2238,8 +2236,8 @@ struct
22382236 let deep_args = LibraryDesc.Accesses. find desc.accs { kind = Spawn ; deep = true } args in
22392237 let shallow_flist = collect_invalidate ~deep: false ~man man.local shallow_args in
22402238 let deep_flist = collect_invalidate ~deep: true ~man man.local deep_args in
2241- let flist = shallow_flist @ deep_flist in
2242- let addrs = List. concat_map AD. to_var_may flist in
2239+ let flist = AD. join shallow_flist deep_flist in
2240+ let addrs = AD. to_var_may flist in
22432241 if addrs <> [] then M. debug ~category: Analyzer " Spawning non-unique functions from unknown function: %a" (d_list " , " CilType.Varinfo. pretty) addrs;
22442242 List. filter_map (create_thread ~multiple: true None None ) addrs
22452243
0 commit comments