@ -6,16 +6,10 @@
* )
* )
open ! IStd
open ! IStd
(* * Eradicate NPEs. *)
module L = Logging
module L = Logging
module F = Format
module F = Format
open Dataflow
open Dataflow
(* ERADICATE CHECKER. TODOS: *)
(* 1 ) add support for constructors for anonymous inner classes ( currently not checked ) *)
(* * Type for a module that provides a main callback function *)
(* * Type for a module that provides a main callback function *)
module type CallBackT = sig
module type CallBackT = sig
val callback : TypeCheck . checks -> Callbacks . proc_callback_t
val callback : TypeCheck . checks -> Callbacks . proc_callback_t
@ -120,16 +114,15 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
( ! calls_this , None )
( ! calls_this , None )
let callback2 tenv curr_pname calls_this checks { Callbacks . summary ; get_procs_in_file }
let analyze_procedure tenv proc_name proc_desc calls_this checks Callbacks . { get_procs_in_file }
annotated_signature linereader proc_loc : unit =
annotated_signature linereader proc_loc : unit =
let curr_pdesc = Summary . get_proc_desc summary in
let idenv = Idenv . create proc_desc in
let idenv = Idenv . create curr_pdesc in
let find_duplicate_nodes = State . mk_find_duplicate_nodes proc_desc in
let find_duplicate_nodes = State . mk_find_duplicate_nodes curr_pdesc in
let find_canonical_duplicate node =
let find_canonical_duplicate node =
let duplicate_nodes = find_duplicate_nodes node in
let duplicate_nodes = find_duplicate_nodes node in
try Procdesc . NodeSet . min_elt duplicate_nodes with Caml . Not_found -> node
try Procdesc . NodeSet . min_elt duplicate_nodes with Caml . Not_found -> node
in
in
let caller_nullsafe_mode = NullsafeMode . of_procname tenv curr _p name in
let caller_nullsafe_mode = NullsafeMode . of_procname tenv pro c_name in
let typecheck_proc do_checks pname pdesc proc_details_opt =
let typecheck_proc do_checks pname pdesc proc_details_opt =
let ann_sig , loc , idenv_pn =
let ann_sig , loc , idenv_pn =
match proc_details_opt with
match proc_details_opt with
@ -158,23 +151,22 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
in
in
let do_final_typestate typestate_opt calls_this =
let do_final_typestate typestate_opt calls_this =
let do_typestate typestate =
let do_typestate typestate =
let start_node = Procdesc . get_start_node curr _p desc in
let start_node = Procdesc . get_start_node pro c_desc in
if
if
( not calls_this )
( not calls_this )
(* if 'this ( ... ) ' is called, no need to check initialization *)
(* if 'this ( ... ) ' is called, no need to check initialization *)
&& checks . TypeCheck . eradicate
&& checks . TypeCheck . eradicate
then (
then (
let typestates_for_curr_constructor_and_all_initializer_methods =
let typestates_for_curr_constructor_and_all_initializer_methods =
Initializers . final_initializer_typestates_lazy tenv curr _p name curr _p desc
Initializers . final_initializer_typestates_lazy tenv pro c_name pro c_desc
get_procs_in_file typecheck_proc
get_procs_in_file typecheck_proc
in
in
let typestates_for_all_constructors_incl_current =
let typestates_for_all_constructors_incl_current =
Initializers . final_constructor_typestates_lazy tenv curr _p name get_procs_in_file
Initializers . final_constructor_typestates_lazy tenv pro c_name get_procs_in_file
typecheck_proc
typecheck_proc
in
in
EradicateChecks . check_constructor_initialization tenv find_canonical_duplicate curr_pname
EradicateChecks . check_constructor_initialization tenv find_canonical_duplicate proc_name
curr_pdesc start_node
proc_desc start_node ~ nullsafe_mode : annotated_signature . AnnotatedSignature . nullsafe_mode
~ nullsafe_mode : annotated_signature . AnnotatedSignature . nullsafe_mode
~ typestates_for_curr_constructor_and_all_initializer_methods
~ typestates_for_curr_constructor_and_all_initializer_methods
~ typestates_for_all_constructors_incl_current proc_loc ;
~ typestates_for_all_constructors_incl_current proc_loc ;
if Config . eradicate_verbose then L . result " Final Typestate@ \n %a@. " TypeState . pp typestate
if Config . eradicate_verbose then L . result " Final Typestate@ \n %a@. " TypeState . pp typestate
@ -182,52 +174,54 @@ module MkCallback (Extension : ExtensionT) : CallBackT = struct
in
in
match typestate_opt with None -> () | Some typestate -> do_typestate typestate
match typestate_opt with None -> () | Some typestate -> do_typestate typestate
in
in
TypeErr . reset () ;
let calls_this , final_typestate_opt =
let calls_this , final_typestate_opt =
typecheck_proc true curr _p name curr _p desc ( Some ( annotated_signature , proc_loc , idenv ) )
typecheck_proc true pro c_name pro c_desc ( Some ( annotated_signature , proc_loc , idenv ) )
in
in
do_final_typestate final_typestate_opt calls_this ;
do_final_typestate final_typestate_opt calls_this ;
if checks . TypeCheck . eradicate then
if checks . TypeCheck . eradicate then
EradicateChecks . check_overridden_annotations find_canonical_duplicate tenv curr_pname
EradicateChecks . check_overridden_annotations find_canonical_duplicate tenv proc_name proc_desc
curr_pdesc annotated_signature ;
annotated_signature ;
TypeErr . report_forall_checks_and_reset ( EradicateCheckers . report_error tenv ) curr_pdesc ;
()
()
(* * Entry point for the eradicate-based checker infrastructure. *)
(* If we need to skip analysis, returns a string reason for debug, otherwise None *)
let find_reason_to_skip_analysis proc_name proc_desc =
match proc_name with
| Procname . Java java_pname ->
if Procname . Java . is_access_method java_pname then Some " access method "
else if Procname . Java . is_external java_pname then Some " third party method "
else if ( Procdesc . get_attributes proc_desc ) . ProcAttributes . is_bridge_method then
Some " bridge method "
else None
| _ ->
Some " not a Java method "
(* * Entry point for the nullsafe procedure-level analysis. *)
let callback checks ( { Callbacks . summary } as callback_args ) : Summary . t =
let callback checks ( { Callbacks . summary } as callback_args ) : Summary . t =
let proc_desc = Summary . get_proc_desc summary in
let proc_desc = Summary . get_proc_desc summary in
let proc_name = Procdesc . get_proc_name proc_desc in
let proc_name = Procdesc . get_proc_name proc_desc in
L . debug Analysis Medium " Analysis of %a@ \n " Procname . pp proc_name ;
match find_reason_to_skip_analysis proc_name proc_desc with
| Some reason ->
L . debug Analysis Medium " Skipping analysis: %s@ \n " reason ;
summary
| None ->
(* start the analysis! *)
let calls_this = ref false in
let calls_this = ref false in
let curr_pname = Summary . get_proc_name summary in
let tenv = Exe_env . get_tenv callback_args . exe_env proc_name in
let tenv = Exe_env . get_tenv callback_args . exe_env curr_pname in
let filter_special_cases () =
if
( match proc_name with
| Procname . Java java_pname ->
Procname . Java . is_access_method java_pname | | Procname . Java . is_external java_pname
| _ ->
false )
| | ( Procdesc . get_attributes proc_desc ) . ProcAttributes . is_bridge_method
then None
else
let annotated_signature =
let annotated_signature =
(* TODO ( T62825735 ) : fully support trusted callees; this could benefit from refactoring *)
Models . get_modelled_annotated_signature ~ is_trusted_callee : false tenv
Models . get_modelled_annotated_signature ~ is_trusted_callee : false tenv
( Procdesc . get_attributes proc_desc )
( Procdesc . get_attributes proc_desc )
in
in
Some annotated_signature
L . debug Analysis Medium " Signature: %a@ \n " ( AnnotatedSignature . pp proc_name )
in
annotated_signature ;
( match filter_special_cases () with
| None ->
()
| Some annotated_signature ->
let loc = Procdesc . get_loc proc_desc in
let loc = Procdesc . get_loc proc_desc in
let linereader = Printer . LineReader . create () in
let linereader = Printer . LineReader . create () in
if Config . eradicate_verbose then
TypeErr . reset () ;
L . result " %a@. " ( AnnotatedSignature . pp proc_name ) annotated_signature ;
analyze_procedure tenv proc_name proc_desc calls_this checks callback_args
callback2 tenv curr_pname calls_this checks callback_args annotated_signature linereader loc
annotated_signature linereader loc ;
) ;
TypeErr . report_forall_checks_and_reset ( EradicateCheckers . report_error tenv ) proc_desc ;
summary
summary
end
end