@ -168,10 +168,12 @@ let report_calls_and_accesses tenv callback proc_desc instr =
| None -> ()
(* * Report all field accesses and method calls of a procedure. *)
let callback_check_access { Callbacks . tenv ; proc_desc } =
let callback_check_access { Callbacks . tenv ; proc_desc ; } =
Procdesc . iter_instrs
( fun _ instr -> report_calls_and_accesses tenv Localise . proc_callback proc_desc instr )
proc_desc
proc_desc ;
Specs . get_summary_unsafe " callback_check_access " ( Procdesc . get_proc_name proc_desc )
(* * Report all field accesses and method calls of a class. *)
let callback_check_cluster_access exe_env all_procs get_proc_desc _ =
@ -189,7 +191,8 @@ let callback_check_cluster_access exe_env all_procs get_proc_desc _ =
(* * Looks for writeToParcel methods and checks whether read is in reverse *)
let callback_check_write_to_parcel_java
pname_java ( { Callbacks . tenv ; proc_desc ; idenv ; get_proc_desc } as args ) =
pname_java { Callbacks . tenv ; proc_desc ; idenv ; get_proc_desc } =
let proc_name = Procdesc . get_proc_name proc_desc in
let verbose = ref false in
let is_write_to_parcel this_expr this_type =
@ -265,17 +268,17 @@ let callback_check_write_to_parcel_java
| rc :: rcs , wc :: wcs ->
if not ( is_inverse rc wc ) then
L . stdout " Serialization missmatch in %a for %a and %a@. "
Typ . Procname . pp args. Callbacks . proc_name
Typ . Procname . pp proc_name
Typ . Procname . pp rc
Typ . Procname . pp wc
else
check_match ( rcs , wcs )
| rc :: _ , [] ->
L . stdout " Missing write in %a: for %a@. "
Typ . Procname . pp args. Callbacks . proc_name Typ . Procname . pp rc
Typ . Procname . pp proc_name Typ . Procname . pp rc
| _ , wc :: _ ->
L . stdout " Missing read in %a: for %a@. "
Typ . Procname . pp args. Callbacks . proc_name Typ . Procname . pp wc
Typ . Procname . pp proc_name Typ . Procname . pp wc
| _ ->
() in
@ -287,7 +290,7 @@ let callback_check_write_to_parcel_java
if is_write_to_parcel this_exp this_type then begin
if ! verbose then
L . stdout " Serialization check for %a@. "
Typ . Procname . pp args. Callbacks . proc_name;
Typ . Procname . pp proc_name;
try
match parcel_constructors tenv this_type with
| x :: _ ->
@ -296,7 +299,7 @@ let callback_check_write_to_parcel_java
| None -> raise Not_found )
| _ ->
L . stdout " No parcel constructor found for %a@. "
Typ . Procname . pp args. Callbacks . proc_name
Typ . Procname . pp proc_name
with Not_found ->
if ! verbose then L . stdout " Methods not available@. "
end
@ -304,15 +307,18 @@ let callback_check_write_to_parcel_java
Procdesc . iter_instrs do_instr proc_desc
(* * Looks for writeToParcel methods and checks whether read is in reverse *)
let callback_check_write_to_parcel ( { Callbacks . proc_name } as args ) =
match proc_name with
| Typ . Procname . Java pname_java ->
callback_check_write_to_parcel_java pname_java args
| _ ->
()
let callback_check_write_to_parcel ( { Callbacks . summary } as args ) =
begin
match Specs . get_proc_name summary with
| Typ . Procname . Java pname_java ->
callback_check_write_to_parcel_java pname_java args
| _ -> ()
end ;
summary
(* * Monitor calls to Preconditions.checkNotNull and detect inconsistent uses. *)
let callback_monitor_nullcheck { Callbacks . proc_desc ; idenv ; proc_name } =
let callback_monitor_nullcheck { Callbacks . proc_desc ; idenv } =
let proc_name = Procdesc . get_proc_name proc_desc in
let verbose = ref false in
let class_formal_names = lazy (
@ -389,23 +395,28 @@ let callback_monitor_nullcheck { Callbacks.proc_desc; idenv; proc_name } =
() )
| _ -> () in
Procdesc . iter_instrs do_instr proc_desc ;
summary_checks_of_formals ()
summary_checks_of_formals () ;
Specs . get_summary_unsafe " callback_monitor_nullcheck " proc_name
(* * Test persistent state. *)
let callback_test_state { Callbacks . proc_name } =
ST . pname_add proc_name " somekey " " somevalue "
let callback_test_state { Callbacks . summary } =
let proc_name = Specs . get_proc_name summary in
ST . pname_add proc_name " somekey " " somevalue " ;
Specs . get_summary_unsafe " callback_test_state " proc_name
(* * Check the uses of VisibleForTesting *)
let callback_checkVisibleForTesting { Callbacks . proc_desc } =
let callback_checkVisibleForTesting { Callbacks . proc_desc ; summary } =
if Annotations . pdesc_return_annot_ends_with proc_desc Annotations . visibleForTesting then
begin
let loc = Procdesc . get_loc proc_desc in
let linereader = Printer . LineReader . create () in
L . stdout " %a@. " ( PP . pp_loc_range linereader 10 10 ) loc
end
end ;
summary
(* * Check for readValue and readValueAs json deserialization *)
let callback_find_deserialization { Callbacks . proc_desc ; get_proc_desc ; idenv ; proc_name } =
let callback_find_deserialization { Callbacks . proc_desc ; get_proc_desc ; idenv ; } =
let proc_name = Procdesc . get_proc_name proc_desc in
let verbose = true in
let ret_const_key = " return_const " in
@ -498,10 +509,11 @@ let callback_find_deserialization { Callbacks.proc_desc; get_proc_desc; idenv; p
ST . pname_add proc_name ret_const_key ret_const in
store_return () ;
Procdesc . iter_instrs do_instr proc_desc
Procdesc . iter_instrs do_instr proc_desc ;
Specs . get_summary_unsafe " callback_find_deserialization " proc_name
(* * Check field accesses. *)
let callback_check_field_access { Callbacks . proc_desc } =
let callback_check_field_access { Callbacks . proc_desc ; summary } =
let rec do_exp is_read = function
| Exp . Var _ -> ()
| Exp . UnOp ( _ , e , _ ) ->
@ -541,10 +553,12 @@ let callback_check_field_access { Callbacks.proc_desc } =
| Sil . Remove_temps _
| Sil . Declare_locals _ ->
() in
Procdesc . iter_instrs do_instr proc_desc
Procdesc . iter_instrs do_instr proc_desc ;
summary
(* * Print c method calls. *)
let callback_print_c_method_calls { Callbacks . tenv ; proc_desc ; proc_name } =
let callback_print_c_method_calls { Callbacks . tenv ; proc_desc } =
let proc_name = Procdesc . get_proc_name proc_desc in
let do_instr node = function
| Sil . Call ( _ , Exp . Const ( Const . Cfun pn ) , ( e , _ ) :: _ , loc , _ )
when Typ . Procname . is_c_method pn ->
@ -569,10 +583,12 @@ let callback_print_c_method_calls { Callbacks.tenv; proc_desc; proc_name } =
loc
description
| _ -> () in
Procdesc . iter_instrs do_instr proc_desc
Procdesc . iter_instrs do_instr proc_desc ;
Specs . get_summary_unsafe " callback_print_c_method_calls " proc_name
(* * Print access to globals. *)
let callback_print_access_to_globals { Callbacks . tenv ; proc_desc ; proc_name } =
let callback_print_access_to_globals { Callbacks . tenv ; proc_desc } =
let proc_name = Procdesc . get_proc_name proc_desc in
let do_pvar is_read pvar loc =
let description =
Printf . sprintf " %s of global %s "
@ -597,4 +613,5 @@ let callback_print_access_to_globals { Callbacks.tenv; proc_desc; proc_name } =
| Sil . Store ( e , _ , _ , loc ) when get_global_var e < > None ->
Option . iter ~ f : ( fun pvar -> do_pvar false pvar loc ) ( get_global_var e )
| _ -> () in
Procdesc . iter_instrs do_instr proc_desc
Procdesc . iter_instrs do_instr proc_desc ;
Specs . get_summary_unsafe " callback_print_access_to_globals " proc_name