[checkers] add --<checker>-only options

Summary:
This makes it easier to test a single checker.

Also refactor the code to make it harder to mess up the list of default/all checkers.

Reviewed By: sblackshear

Differential Revision: D5583209

fbshipit-source-id: 7c919b2
master
Jules Villard 7 years ago committed by Facebook Github Bot
parent 6505fa694d
commit 52746fd9eb

@ -597,7 +597,6 @@ and ( annotation_reachability
, biabduction , biabduction
, bufferoverrun , bufferoverrun
, crashcontext , crashcontext
, default_checkers
, eradicate , eradicate
, fragment_retains_view , fragment_retains_view
, immutable_cast , immutable_cast
@ -608,85 +607,71 @@ and ( annotation_reachability
, siof , siof
, threadsafety , threadsafety
, suggest_nullable ) = , suggest_nullable ) =
let all_checkers = ref [] in
let default_checkers = ref [] in
let mk_checker ?(default= false) ~long doc =
let var = CLOpt.mk_bool ~long ~in_help:CLOpt.([(Analyze, manual_generic)]) ~default doc in
all_checkers := (var, long) :: !all_checkers ;
if default then default_checkers := (var, long) :: !default_checkers ;
var
in
let annotation_reachability = let annotation_reachability =
CLOpt.mk_bool ~long:"annotation-reachability" mk_checker ~default:true ~long:"annotation-reachability"
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true
"the annotation reachability checker. Given a pair of source and sink annotation, e.g. @PerformanceCritical and @Expensive, this checker will warn whenever some method annotated with @PerformanceCritical calls, directly or indirectly, another method annotated with @Expensive" "the annotation reachability checker. Given a pair of source and sink annotation, e.g. @PerformanceCritical and @Expensive, this checker will warn whenever some method annotated with @PerformanceCritical calls, directly or indirectly, another method annotated with @Expensive"
and biabduction = and biabduction =
CLOpt.mk_bool ~long:"biabduction" mk_checker ~long:"biabduction"
~in_help:CLOpt.([(Analyze, manual_generic)])
"the separation logic based bi-abduction analysis using the checkers framework" "the separation logic based bi-abduction analysis using the checkers framework"
and bufferoverrun = and bufferoverrun = mk_checker ~long:"bufferoverrun" "the buffer overrun analysis"
CLOpt.mk_bool ~long:"bufferoverrun"
~in_help:CLOpt.([(Analyze, manual_generic)])
"the buffer overrun analysis"
and crashcontext = and crashcontext =
CLOpt.mk_bool ~long:"crashcontext" mk_checker ~long:"crashcontext"
~in_help:CLOpt.([(Analyze, manual_generic)])
"the crashcontext checker for Java stack trace context reconstruction" "the crashcontext checker for Java stack trace context reconstruction"
and eradicate = and eradicate =
CLOpt.mk_bool ~long:"eradicate" mk_checker ~long:"eradicate" "the eradicate @Nullable checker for Java annotations"
~in_help:CLOpt.([(Analyze, manual_generic)])
"the eradicate @Nullable checker for Java annotations"
and fragment_retains_view = and fragment_retains_view =
CLOpt.mk_bool ~long:"fragment-retains-view" mk_checker ~long:"fragment-retains-view" ~default:true
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true
"detects when Android fragments are not explicitly nullified before becoming unreabable" "detects when Android fragments are not explicitly nullified before becoming unreabable"
and immutable_cast = and immutable_cast =
CLOpt.mk_bool ~long:"immutable-cast" mk_checker ~long:"immutable-cast" ~default:true
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true
"the detection of object cast from immutable type to mutable type. For instance, it will detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set." "the detection of object cast from immutable type to mutable type. For instance, it will detect cast from ImmutableList to List, ImmutableMap to Map, and ImmutableSet to Set."
and liveness = and liveness =
CLOpt.mk_bool ~long:"liveness" mk_checker ~long:"liveness" ~default:true "the detection of dead stores and unused variables"
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true "the detection of dead stores and unused variables"
and printf_args = and printf_args =
CLOpt.mk_bool ~long:"printf-args" mk_checker ~long:"printf-args" ~default:true
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true
"the detection of mismatch between the Java printf format strings and the argument types For, example, this checker will warn about the type error in `printf(\"Hello %d\", \"world\")`" "the detection of mismatch between the Java printf format strings and the argument types For, example, this checker will warn about the type error in `printf(\"Hello %d\", \"world\")`"
and repeated_calls = and repeated_calls = mk_checker ~long:"repeated-calls" "check for repeated calls"
CLOpt.mk_bool ~long:"repeated-calls" and quandary = mk_checker ~long:"quandary" ~default:true "the quandary taint analysis"
~in_help:CLOpt.([(Analyze, manual_generic)])
"check for repeated calls"
and quandary =
CLOpt.mk_bool ~long:"quandary"
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true "the quandary taint analysis"
and siof = and siof =
CLOpt.mk_bool ~long:"siof" mk_checker ~long:"siof" ~default:true
~in_help:CLOpt.([(Analyze, manual_generic)]) "the Static Initialization Order Fiasco analysis (C++ only)"
~default:true "the Static Initialization Order Fiasco analysis (C++ only)" and threadsafety = mk_checker ~long:"threadsafety" ~default:true "the thread safety analysis"
and threadsafety =
CLOpt.mk_bool ~long:"threadsafety"
~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true "the thread safety analysis"
and suggest_nullable = and suggest_nullable =
CLOpt.mk_bool ~long:"suggest-nullable" ~default:false mk_checker ~long:"suggest-nullable" ~default:false
"Nullable annotation sugesstions analysis (experimental)" "Nullable annotation sugesstions analysis (experimental)"
in in
(* IMPORTANT: keep in sync with the checkers that have ~default:true above *) let mk_only (var, long) =
let default_checkers = let _ : bool ref =
CLOpt.mk_bool_group ~long:(long ^ "-only")
~in_help:CLOpt.([(Analyze, manual_generic)])
(Printf.sprintf "Enable $(b,--%s) and disable all other checkers" long) [var]
(List.map ~f:fst !all_checkers)
in
()
in
List.iter ~f:mk_only !all_checkers ;
let _default_checkers : bool ref =
CLOpt.mk_bool_group ~long:"default-checkers" CLOpt.mk_bool_group ~long:"default-checkers"
~in_help:CLOpt.([(Analyze, manual_generic)]) ~in_help:CLOpt.([(Analyze, manual_generic)])
~default:true ~default:true
"Default checkers: $(b,--annotation-reachability), $(b,--fragments-retains-view), $(b,--immutable-cast), $(b,--printf-args), $(b,--quandary), $(b,--siof), $(b,--threadsafety)" ( "Default checkers: "
[ annotation_reachability ^ ( List.map ~f:(fun (_, s) -> Printf.sprintf "$(b,--%s)" s) !default_checkers
; fragment_retains_view |> String.concat ~sep:", " ) )
; immutable_cast (List.map ~f:fst !default_checkers)
; printf_args []
; quandary
; siof
; threadsafety ] []
in in
( annotation_reachability ( annotation_reachability
, biabduction , biabduction
, bufferoverrun , bufferoverrun
, crashcontext , crashcontext
, default_checkers
, eradicate , eradicate
, fragment_retains_view , fragment_retains_view
, immutable_cast , immutable_cast
@ -1243,7 +1228,7 @@ and linters_def_folder =
~in_help:CLOpt.([(Capture, manual_clang_linters)]) ~in_help:CLOpt.([(Capture, manual_clang_linters)])
~meta:"dir" "Specify the folder containing linters files with extension .al" ~meta:"dir" "Specify the folder containing linters files with extension .al"
in in
let _ = let () =
CLOpt.mk_set linters_def_folder [] ~long:"reset-linters-def-folder" CLOpt.mk_set linters_def_folder [] ~long:"reset-linters-def-folder"
"Reset the list of folders containing linters definitions to be empty (see $(b,linters-def-folder))." "Reset the list of folders containing linters definitions to be empty (see $(b,linters-def-folder))."
in in
@ -1547,7 +1532,7 @@ and specs_library =
CLOpt.mk_path_list ~deprecated:["lib"] ~long:"specs-library" ~short:'L' ~meta:"dir|jar" CLOpt.mk_path_list ~deprecated:["lib"] ~long:"specs-library" ~short:'L' ~meta:"dir|jar"
"Search for .spec files in given directory or jar file" "Search for .spec files in given directory or jar file"
in in
let _ = let _ : string ref =
(* Given a filename with a list of paths, convert it into a list of string iff they are (* Given a filename with a list of paths, convert it into a list of string iff they are
absolute *) absolute *)
let read_specs_dir_list_file fname = let read_specs_dir_list_file fname =
@ -1951,8 +1936,6 @@ and debug_exceptions = !debug_exceptions
and debug_mode = !debug and debug_mode = !debug
and default_checkers = !default_checkers
and default_linters = !default_linters and default_linters = !default_linters
and dependency_mode = !dependencies and dependency_mode = !dependencies

@ -106,8 +106,6 @@ val relative_cpp_models_dir : string
val csl_analysis : bool val csl_analysis : bool
val default_checkers : bool
val default_failure_name : string val default_failure_name : string
val default_in_zip_results_dir : string val default_in_zip_results_dir : string

@ -12,7 +12,7 @@ The `ResourceLeaks.ml` and `ResourceLeaksDomain.ml` files have comments containi
(c) Add a new test method containing a resource leak to `Leaks.java`, then run the tests again. The tests should now fail, and the error message should indicate that the failure is due to the new lreeak that you added. As the message suggests, run `make replace` to update the expected output (this simply copies the actual output `issues.exp.test` to the expected output `issues.exp`). Re-run the tests; they should now pass again. (c) Add a new test method containing a resource leak to `Leaks.java`, then run the tests again. The tests should now fail, and the error message should indicate that the failure is due to the new lreeak that you added. As the message suggests, run `make replace` to update the expected output (this simply copies the actual output `issues.exp.test` to the expected output `issues.exp`). Re-run the tests; they should now pass again.
(d) Run the analyzer on a single test file to produce the debug HTML: `infer --debug -a checkers --no-default-checkers --resource-leak -- javac Leaks.java`. Then, open the debug HTML: `open infer-out/captured/*.html`. This helpful artifact shows the Infer warnings alongside the code they are complaining about. It also displays the CFG node(s) associated with each line of code. Clicking a CFG node shows the Infer IR associated with the node, and the pre/post state computed while analyzing the instruction. Come back to the debug HTML early and often when you can't understand what your analysis is doing--it will help! (d) Run the analyzer on a single test file to produce the debug HTML: `infer --debug -a checkers --resource-leak-only -- javac Leaks.java`. Then, open the debug HTML: `open infer-out/captured/*.html`. This helpful artifact shows the Infer warnings alongside the code they are complaining about. It also displays the CFG node(s) associated with each line of code. Clicking a CFG node shows the Infer IR associated with the node, and the pre/post state computed while analyzing the instruction. Come back to the debug HTML early and often when you can't understand what your analysis is doing--it will help!
(e) The `Logging.d_str`/`Logging.d_strln` functions print to the debug HTML. The logging is contextual: it will print to the log for the CFG node that's being analyzed at the time the logging statement execute. Try adding `Logging.d_strln "Hi Infer";` inside of the case for `Call`, recompiling/re-running. You should see the text you printed inside the appropriate CFG node log in the debug HTML. (e) The `Logging.d_str`/`Logging.d_strln` functions print to the debug HTML. The logging is contextual: it will print to the log for the CFG node that's being analyzed at the time the logging statement execute. Try adding `Logging.d_strln "Hi Infer";` inside of the case for `Call`, recompiling/re-running. You should see the text you printed inside the appropriate CFG node log in the debug HTML.
@ -132,7 +132,7 @@ void closeInCatchBad() {
``` ```
(b) Try running on real code! The instructions [here](http://fm.csl.sri.com/SSFT17/infer-instr.html) have several suggestions for open-source Android apps to point your analysis at. Try `./gradlew assembleDebug -x test` first to make sure everything builds correctly without Infer (if not, you are probably missing some dependencies--the error messages should guide you). Once that's working, try (b) Try running on real code! The instructions [here](http://fm.csl.sri.com/SSFT17/infer-instr.html) have several suggestions for open-source Android apps to point your analysis at. Try `./gradlew assembleDebug -x test` first to make sure everything builds correctly without Infer (if not, you are probably missing some dependencies--the error messages should guide you). Once that's working, try
`./gradlew clean; infer -a checkers --no-default-checkers --resource-leak -- ./gradlew assembleDebug -x test`. `./gradlew clean; infer -a checkers --resource-leak-only -- ./gradlew assembleDebug -x test`.
- Found a real bug? Bonus points! Send a pull request to fix it! Very frequently, the best fix is to use try-with-resources. - Found a real bug? Bonus points! Send a pull request to fix it! Very frequently, the best fix is to use try-with-resources.
- Found a false positive in your analysis? Try re-running Infer with `--debug` and see if you can narrow down the root cause/fix it? - Found a false positive in your analysis? Try re-running Infer with `--debug` and see if you can narrow down the root cause/fix it?
- How does your analysis compare to Infer's production resource leak analysis? Run with `infer -- <gradle command>` to see if your analysis finds bugs that Infer misses, or vice versa. - How does your analysis compare to Infer's production resource leak analysis? Run with `infer -- <gradle command>` to see if your analysis finds bugs that Infer misses, or vice versa.

@ -10,7 +10,7 @@ TESTS_DIR = ../../..
ANALYZER = checkers ANALYZER = checkers
# see explanations in cpp/errors/Makefile for the custom isystem # see explanations in cpp/errors/Makefile for the custom isystem
CLANG_OPTIONS = -x c++ -std=c++11 -nostdinc++ -isystem$(MODELS_DIR)/cpp/include -isystem$(CLANG_INCLUDES)/c++/v1/ -c CLANG_OPTIONS = -x c++ -std=c++11 -nostdinc++ -isystem$(MODELS_DIR)/cpp/include -isystem$(CLANG_INCLUDES)/c++/v1/ -c
INFER_OPTIONS = --ml-buckets cpp --debug-exceptions --project-root $(TESTS_DIR) --no-keep-going INFER_OPTIONS = --liveness --ml-buckets cpp --debug-exceptions --project-root $(TESTS_DIR) --no-keep-going
INFERPRINT_OPTIONS = --issues-tests INFERPRINT_OPTIONS = --issues-tests
SOURCES = $(wildcard *.cpp) SOURCES = $(wildcard *.cpp)

Loading…
Cancel
Save