[infer][ondemand] run all the registered checkers in sequence

Summary: Run all the checkers one after each other, which allows the Infer AI framework to run several checkers together, including the possibility for them to collaborate.

Reviewed By: sblackshear

Differential Revision: D4621838

fbshipit-source-id: e264d67
master
Jeremy Dubreil 8 years ago committed by Facebook Github Bot
parent 34106a2056
commit e23b04180e

@ -89,32 +89,31 @@ let iterate_procedure_callbacks exe_env caller_pname =
Specs.add_summary proc_name summary; Specs.add_summary proc_name summary;
summary in summary in
let initial_summary = reset_summary caller_pname in
match get_procedure_definition exe_env caller_pname with match get_procedure_definition exe_env caller_pname with
| None -> () | None -> initial_summary
| Some (idenv, tenv, proc_name, proc_desc, _) -> | Some (idenv, tenv, _, proc_desc, _) ->
ignore List.fold
(List.fold ~init:initial_summary
~init:(reset_summary proc_name) ~f:(fun summary (language_opt, proc_callback) ->
~f:(fun summary (language_opt, proc_callback) -> let language_matches = match language_opt with
let language_matches = match language_opt with | Some language -> Config.equal_language language procedure_language
| Some language -> Config.equal_language language procedure_language | None -> true in
| None -> true in if language_matches then
if language_matches then let init_time = Unix.gettimeofday () in
let init_time = Unix.gettimeofday () in proc_callback
proc_callback {
{ get_proc_desc;
get_proc_desc; get_procs_in_file;
get_procs_in_file; idenv;
idenv; tenv;
tenv; summary;
summary; proc_desc;
proc_desc; }
} |> update_time (Unix.gettimeofday () -. init_time)
|> update_time (Unix.gettimeofday () -. init_time) else
else summary)
summary) !procedure_callbacks
!procedure_callbacks);
Specs.store_summary (Specs.get_summary_unsafe "iterate_procedure_callbacks" proc_name)
(** Invoke all registered cluster callbacks on a cluster of procedures. *) (** Invoke all registered cluster callbacks on a cluster of procedures. *)
@ -154,10 +153,26 @@ let iterate_callbacks call_graph exe_env =
(* Make sure summaries exists. *) (* Make sure summaries exists. *)
List.iter ~f:(fun p -> ignore (reset_summary p)) procs_to_analyze; List.iter ~f:(fun p -> ignore (reset_summary p)) procs_to_analyze;
(* Invoke procedure callbacks. *) let analyze_ondemand _ proc_desc =
List.iter let proc_name = Procdesc.get_proc_name proc_desc in
~f:(iterate_procedure_callbacks exe_env) iterate_procedure_callbacks exe_env proc_name in
procs_to_analyze;
let callbacks = {
Ondemand.analyze_ondemand;
get_proc_desc = Exe_env.get_proc_desc exe_env
} in
(* Create and register on-demand analysis callback *)
let analyze_proc_name pname =
match Ondemand.get_proc_desc pname with
| None ->
failwithf "Could not find proc desc for %a" Typ.Procname.pp pname
| Some pdesc ->
ignore (Ondemand.analyze_proc_desc ~propagate_exceptions:true pdesc pdesc) in
Ondemand.set_callbacks callbacks;
(* Invoke procedure callbacks using on-demand anlaysis schedulling *)
List.iter ~f:analyze_proc_name procs_to_analyze;
let originally_defined_procs = let originally_defined_procs =
Cg.get_defined_nodes call_graph in Cg.get_defined_nodes call_graph in
@ -185,6 +200,9 @@ let iterate_callbacks call_graph exe_env =
~f:(iterate_cluster_callbacks originally_defined_procs exe_env) ~f:(iterate_cluster_callbacks originally_defined_procs exe_env)
(cluster procs_to_analyze); (cluster procs_to_analyze);
(* Unregister callbacks *)
Ondemand.unset_callbacks ();
(* Store all the summaries to disk *) (* Store all the summaries to disk *)
List.iter List.iter
~f:(fun pname -> ~f:(fun pname ->

@ -159,35 +159,14 @@ end
module Interprocedural (Summ : Summary.S) = struct module Interprocedural (Summ : Summary.S) = struct
let compute_and_store_post let compute_and_store_post
~compute_post ~make_extras { Callbacks.get_proc_desc; proc_desc; tenv; } = ~compute_post ~make_extras { Callbacks.proc_desc; tenv; } =
let proc_name = Procdesc.get_proc_name proc_desc in match compute_post (ProcData.make proc_desc tenv (make_extras proc_desc)) with
let analyze_ondemand_ _ pdesc = | Some post ->
match compute_post (ProcData.make pdesc tenv (make_extras pdesc)) with Summ.write_summary (Procdesc.get_proc_name proc_desc) post;
| Some post -> Some post
Summ.write_summary (Procdesc.get_proc_name pdesc) post; | None ->
Some post None
| None ->
None in
let analyze_ondemand source pdesc =
ignore (analyze_ondemand_ source pdesc);
Specs.get_summary_unsafe
"Inferprocedural.compute_and_store_post"
(Procdesc.get_proc_name pdesc) in
let callbacks =
{
Ondemand.analyze_ondemand;
get_proc_desc;
} in
if Ondemand.procedure_should_be_analyzed proc_name
then
begin
Ondemand.set_callbacks callbacks;
let post_opt = analyze_ondemand_ SourceFile.empty proc_desc in
Ondemand.unset_callbacks ();
post_opt
end
else
Summ.read_summary proc_desc proc_name
end end
module MakeWithScheduler (C : ProcCfg.S) (S : Scheduler.Make) (T : TransferFunctions.Make) = module MakeWithScheduler (C : ProcCfg.S) (S : Scheduler.Make) (T : TransferFunctions.Make) =

@ -153,8 +153,8 @@ let method_has_annot annot tenv pname =
let method_overrides_annot annot tenv pname = let method_overrides_annot annot tenv pname =
method_overrides (method_has_annot annot) tenv pname method_overrides (method_has_annot annot) tenv pname
let lookup_annotation_calls annot pname : CallSite.t list = let lookup_annotation_calls caller_pdesc annot pname : CallSite.t list =
match Specs.get_summary pname with match Ondemand.analyze_proc_name ~propagate_exceptions:false caller_pdesc pname with
| Some { Specs.payload = { Specs.calls = Some call_map; }; } -> | Some { Specs.payload = { Specs.calls = Some call_map; }; } ->
begin begin
try try
@ -381,7 +381,7 @@ module Interprocedural = struct
report_annotation_stack src_annot.class_name snk_annot.class_name in report_annotation_stack src_annot.class_name snk_annot.class_name in
report_call_stack report_call_stack
(method_has_annot snk_annot tenv) (method_has_annot snk_annot tenv)
(lookup_annotation_calls snk_annot) (lookup_annotation_calls proc_desc snk_annot)
f_report f_report
(CallSite.make proc_name loc) (CallSite.make proc_name loc)
calls in calls in

@ -39,7 +39,7 @@ module Make (H : Helper) = struct
match Specs.get_summary pname with match Specs.get_summary pname with
| Some global_summary -> | Some global_summary ->
let payload = H.update_payload summary global_summary.Specs.payload in let payload = H.update_payload summary global_summary.Specs.payload in
Specs.store_summary { global_summary with payload; } Specs.add_summary pname { global_summary with payload; }
| None -> | None ->
failwithf "Summary for %a should exist, but does not!@." Typ.Procname.pp pname failwithf "Summary for %a should exist, but does not!@." Typ.Procname.pp pname

@ -405,39 +405,14 @@ module Main =
Build(EmptyExtension) Build(EmptyExtension)
(** Eradicate checker for Java @Nullable annotations. *) (** Eradicate checker for Java @Nullable annotations. *)
let callback_eradicate let callback_eradicate =
({ Callbacks.get_proc_desc; summary } as callback_args) =
let checks = let checks =
{ {
TypeCheck.eradicate = true; TypeCheck.eradicate = true;
check_extension = false; check_extension = false;
check_ret_type = []; check_ret_type = [];
} in } in
let callbacks = Main.callback checks
let analyze_ondemand _ pdesc =
let idenv_pname = Idenv.create pdesc in
let proc_name = Procdesc.get_proc_name pdesc in
let summary = Specs.get_summary_unsafe "Eradicate.analyze_ondemand" proc_name in
Main.callback checks
{ callback_args with
Callbacks.idenv = idenv_pname;
summary;
proc_desc = pdesc; } in
{
Ondemand.analyze_ondemand;
get_proc_desc;
} in
if Ondemand.procedure_should_be_analyzed (Specs.get_proc_name summary)
then
begin
Ondemand.set_callbacks callbacks;
let final_summary = Main.callback checks callback_args in
Ondemand.unset_callbacks ();
final_summary
end
else
summary
(** Call the given check_return_type at the end of every procedure. *) (** Call the given check_return_type at the end of every procedure. *)
let callback_check_return_type check_return_type callback_args = let callback_check_return_type check_return_type callback_args =

@ -23,7 +23,7 @@ codetoanalyze/java/checkers/ExpensiveInheritanceExample.java, void ExpensiveInhe
codetoanalyze/java/checkers/ExpensiveInheritanceExample.java, void ExpensiveInheritanceExample.reportsAssumingObjectOfTypeA(), 2, CHECKERS_CALLS_EXPENSIVE_METHOD, [] codetoanalyze/java/checkers/ExpensiveInheritanceExample.java, void ExpensiveInheritanceExample.reportsAssumingObjectOfTypeA(), 2, CHECKERS_CALLS_EXPENSIVE_METHOD, []
codetoanalyze/java/checkers/ExpensiveInheritanceExample.java, void ExpensiveInheritanceExample.reportsBecauseFooIsExpensiveInA(A), 1, CHECKERS_CALLS_EXPENSIVE_METHOD, [] codetoanalyze/java/checkers/ExpensiveInheritanceExample.java, void ExpensiveInheritanceExample.reportsBecauseFooIsExpensiveInA(A), 1, CHECKERS_CALLS_EXPENSIVE_METHOD, []
codetoanalyze/java/checkers/ExpensiveInterfaceExample.java, void ExpensiveInterfaceExample$ImplementsInterface.m1(), 1, CHECKERS_CALLS_EXPENSIVE_METHOD, [] codetoanalyze/java/checkers/ExpensiveInterfaceExample.java, void ExpensiveInterfaceExample$ImplementsInterface.m1(), 1, CHECKERS_CALLS_EXPENSIVE_METHOD, []
codetoanalyze/java/checkers/ExpensiveSubtypingExample.java, void ExpensiveSubtypingExample.m3(), 0, CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED, [return from a call to void ExpensiveSubtypingExample.m4()] codetoanalyze/java/checkers/ExpensiveSubtypingExample.java, void ExpensiveSubtypingExample.m3(), 0, CHECKERS_EXPENSIVE_OVERRIDES_UNANNOTATED, []
codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()] codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()]
codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()] codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()]
codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()] codetoanalyze/java/checkers/FragmentRetainsViewExample.java, void FragmentRetainsViewExample.onDestroyView(), 0, CHECKERS_FRAGMENT_RETAINS_VIEW, [return from a call to void FragmentRetainsViewExample.onDestroyView()]

@ -36,10 +36,11 @@ public class Recursion {
safeRecursionCallSink(5, InferTaint.inferSecretSource()); safeRecursionCallSink(5, InferTaint.inferSecretSource());
} }
public static void recursionBad(int i, Object param) { // TODO (#16595757): Requires support for recursion in Ondemand
public static void FN_recursionBad(int i, Object param) {
if (i == 0) return; if (i == 0) return;
InferTaint.inferSensitiveSink(param); InferTaint.inferSensitiveSink(param);
recursionBad(i - 1, InferTaint.inferSecretSource()); FN_recursionBad(i - 1, InferTaint.inferSecretSource());
} }
} }

@ -154,7 +154,6 @@ codetoanalyze/java/quandary/LoggingPrivateData.java, void LoggingPrivateData.log
codetoanalyze/java/quandary/LoggingPrivateData.java, void LoggingPrivateData.logAllSourcesBad(Location,TelephonyManager), 39, QUANDARY_TAINT_ERROR, [return from float Location.getSpeed(),call to int Log.wtf(String,String)] codetoanalyze/java/quandary/LoggingPrivateData.java, void LoggingPrivateData.logAllSourcesBad(Location,TelephonyManager), 39, QUANDARY_TAINT_ERROR, [return from float Location.getSpeed(),call to int Log.wtf(String,String)]
codetoanalyze/java/quandary/LoggingPrivateData.java, void LoggingPrivateData.logAllSourcesBad(Location,TelephonyManager), 39, QUANDARY_TAINT_ERROR, [return from double Location.getLongitude(),call to int Log.wtf(String,String)] codetoanalyze/java/quandary/LoggingPrivateData.java, void LoggingPrivateData.logAllSourcesBad(Location,TelephonyManager), 39, QUANDARY_TAINT_ERROR, [return from double Location.getLongitude(),call to int Log.wtf(String,String)]
codetoanalyze/java/quandary/Recursion.java, void Recursion.callSinkThenDivergeBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Recursion.callSinkThenDiverge(Object),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Recursion.java, void Recursion.callSinkThenDivergeBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Recursion.callSinkThenDiverge(Object),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Recursion.java, void Recursion.recursionBad(int,Object), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Recursion.recursionBad(int,Object)]
codetoanalyze/java/quandary/Recursion.java, void Recursion.safeRecursionCallSinkBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Recursion.safeRecursionCallSink(int,Object),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Recursion.java, void Recursion.safeRecursionCallSinkBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Recursion.safeRecursionCallSink(int,Object),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Strings.java, void Strings.viaFormatterBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Strings.java, void Strings.viaFormatterBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
codetoanalyze/java/quandary/Strings.java, void Strings.viaFormatterIgnoreReturnBad(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] codetoanalyze/java/quandary/Strings.java, void Strings.viaFormatterIgnoreReturnBad(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]

@ -69,6 +69,6 @@ codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.c
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.callVisibleForTestingBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.visibleForTestingNotPublicOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.callVisibleForTestingBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.visibleForTestingNotPublicOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f]
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.deeperTraceBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.callAssignInPrivateMethod(),call to void ThreadSafeExample.assignInPrivateMethodOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.deeperTraceBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.callAssignInPrivateMethod(),call to void ThreadSafeExample.assignInPrivateMethodOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f]
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.oddBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.evenOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.oddBad(), 1, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.evenOk(),access to codetoanalyze.java.checkers.ThreadSafeExample.f]
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.recursiveBad(), 2, THREAD_SAFETY_VIOLATION, [call to void ThreadSafeExample.recursiveBad(),access to codetoanalyze.java.checkers.ThreadSafeExample.f] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.recursiveBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.ThreadSafeExample.f]
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.tsBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.ThreadSafeExample.f] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void ThreadSafeExample.tsBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.ThreadSafeExample.f]
codetoanalyze/java/threadsafety/ThreadSafeExample.java, void YesThreadSafeExtendsNotThreadSafeExample.subsubmethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.YesThreadSafeExtendsNotThreadSafeExample.subsubfield] codetoanalyze/java/threadsafety/ThreadSafeExample.java, void YesThreadSafeExtendsNotThreadSafeExample.subsubmethodBad(), 1, THREAD_SAFETY_VIOLATION, [access to codetoanalyze.java.checkers.YesThreadSafeExtendsNotThreadSafeExample.subsubfield]

Loading…
Cancel
Save