Reviewed By: jeremydubreil Differential Revision: D3066722 fb-gh-sync-id: 0239cc7 shipit-source-id: 0239cc7master
parent
fc5d4897a5
commit
a71caccc80
@ -0,0 +1,50 @@
|
||||
(*
|
||||
* 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.
|
||||
*)
|
||||
|
||||
module PvarSet = PrettyPrintable.MakePPSet(struct
|
||||
type t = Sil.pvar
|
||||
let compare = Sil.pvar_compare
|
||||
let pp_element = (Sil.pp_pvar pe_text)
|
||||
end)
|
||||
|
||||
module Domain = AbstractDomain.FiniteSetDomain(PvarSet)
|
||||
|
||||
module TransferFunctions = struct
|
||||
type astate = Domain.astate
|
||||
|
||||
let rec add_address_taken_pvars exp astate = match exp with
|
||||
| Sil.Lvar pvar ->
|
||||
Domain.add pvar astate
|
||||
| Sil.Cast (_, e) | UnOp (_, e, _) | Lfield (e, _, _) ->
|
||||
add_address_taken_pvars e astate
|
||||
| Sil.BinOp (_, e1, e2) | Lindex (e1, e2) ->
|
||||
add_address_taken_pvars e1 astate
|
||||
|> add_address_taken_pvars e2
|
||||
| Sil.Const (Cclosure _ | Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cattribute _ | Cexn _ | Cclass _
|
||||
| Cptr_to_fld _)
|
||||
| Var _ | Sizeof _ ->
|
||||
astate
|
||||
|
||||
let exec_instr astate = function
|
||||
| Sil.Set (_, Tptr _, rhs_exp, _) ->
|
||||
add_address_taken_pvars rhs_exp astate
|
||||
| Sil.Call (_, _, actuals, _, _) ->
|
||||
let add_actual_by_ref astate_acc = function
|
||||
| actual_exp, Sil.Tptr _ -> add_address_taken_pvars actual_exp astate_acc
|
||||
| _ -> astate_acc in
|
||||
IList.fold_left add_actual_by_ref astate actuals
|
||||
| Sil.Set _ | Letderef _ | Prune _ | Nullify _ | Abstract _ | Remove_temps _ | Stackop _
|
||||
| Declare_locals _ | Goto_node _ ->
|
||||
astate
|
||||
|
||||
end
|
||||
|
||||
module Analyzer =
|
||||
AbstractInterpreter.Make
|
||||
(ProcCfg.Forward) (Scheduler.ReversePostorder) (Domain) (TransferFunctions)
|
@ -0,0 +1,101 @@
|
||||
(*
|
||||
* 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.
|
||||
*)
|
||||
|
||||
module F = Format
|
||||
|
||||
module TestInterpreter = AnalyzerTester.Make
|
||||
(ProcCfg.Forward)
|
||||
(Scheduler.ReversePostorder)
|
||||
(AddressTaken.Domain)
|
||||
(AddressTaken.TransferFunctions)
|
||||
|
||||
let tests =
|
||||
let open OUnit2 in
|
||||
let open AnalyzerTester.StructuredSil in
|
||||
let assert_empty = invariant "{ }" in
|
||||
let int_typ = Sil.Tint IInt in
|
||||
let int_ptr_typ = Sil.Tptr (int_typ, Pk_pointer) in
|
||||
let fun_ptr_typ = Sil.Tptr (Tfun false, Pk_pointer) in
|
||||
let closure_exp captured_pvars =
|
||||
let mk_captured_var str = (ident_of_str str, pvar_of_str str, int_ptr_typ) in
|
||||
let captured_vars = IList.map mk_captured_var captured_pvars in
|
||||
let closure = { Sil.name=dummy_procname; captured_vars; } in
|
||||
Sil.Const (Cclosure closure) in
|
||||
let test_list = [
|
||||
"address_taken_set_instr",
|
||||
[
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "a" "b";
|
||||
invariant "{ &b }"
|
||||
];
|
||||
"address_not_taken_set_instr",
|
||||
[
|
||||
var_assign_var ~rhs_typ:int_typ "a" "b";
|
||||
assert_empty
|
||||
];
|
||||
"address_not_taken_letderef_instr1",
|
||||
[
|
||||
id_assign_var ~rhs_typ:int_ptr_typ "a" "b";
|
||||
assert_empty
|
||||
];
|
||||
"address_not_taken_letderef_instr2",
|
||||
[
|
||||
id_assign_var ~rhs_typ:int_typ "a" "b";
|
||||
assert_empty
|
||||
];
|
||||
"take_multiple_addresses",
|
||||
[
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "a" "b";
|
||||
invariant "{ &b }";
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "c" "d";
|
||||
invariant "{ &b, &d }";
|
||||
var_assign_var ~rhs_typ:int_typ "e" "f";
|
||||
invariant "{ &b, &d }"
|
||||
];
|
||||
"address_not_taken_closure",
|
||||
[
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "a" "b";
|
||||
var_assign_exp ~rhs_typ:fun_ptr_typ "c" (closure_exp ["d"; "e"]);
|
||||
invariant "{ &b }"
|
||||
];
|
||||
"if_conservative1",
|
||||
[
|
||||
If (unknown_exp,
|
||||
[var_assign_var ~rhs_typ:int_ptr_typ "a" "b"],
|
||||
[]
|
||||
);
|
||||
invariant "{ &b }"
|
||||
];
|
||||
"if_conservative2",
|
||||
[
|
||||
If (unknown_exp,
|
||||
[var_assign_var ~rhs_typ:int_ptr_typ "a" "b"],
|
||||
[var_assign_var ~rhs_typ:int_ptr_typ "c" "d"]
|
||||
);
|
||||
invariant "{ &b, &d }"
|
||||
];
|
||||
"loop_as_if",
|
||||
[
|
||||
While (unknown_exp,
|
||||
[var_assign_var ~rhs_typ:int_ptr_typ "a" "b"]
|
||||
);
|
||||
invariant "{ &b }"
|
||||
];
|
||||
"loop_before_after",
|
||||
[
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "a" "b";
|
||||
invariant "{ &b }";
|
||||
While (unknown_exp,
|
||||
[var_assign_var ~rhs_typ:int_ptr_typ "c" "d"]
|
||||
);
|
||||
invariant "{ &b, &d }";
|
||||
var_assign_var ~rhs_typ:int_ptr_typ "e" "f";
|
||||
invariant "{ &b, &d, &f }"
|
||||
];
|
||||
] |> TestInterpreter.create_tests in
|
||||
"address_taken_suite">:::test_list
|
Loading…
Reference in new issue