Whitelist more iterator-related functions and classes

Reviewed By: jeremydubreil

Differential Revision: D5503746

fbshipit-source-id: 945c552
master
Jia Chen 7 years ago committed by Facebook Github Bot
parent 1b35411a5f
commit f658690846

@ -76,15 +76,11 @@ module Match = struct
(* Fail if we detect templates in the fuzzy name. Template instantiations are not taken into (* Fail if we detect templates in the fuzzy name. Template instantiations are not taken into
account when fuzzy matching, and templates may produce wrong results when parsing qualified account when fuzzy matching, and templates may produce wrong results when parsing qualified
names. *) names. *)
let filtered_qual_name = let colon_splits = String.split qual_name ~on:':' in
List.iter colon_splits ~f:(fun s ->
(* Filter out the '<' in operator< and operator<= *) (* Filter out the '<' in operator< and operator<= *)
let operator_less_length = 14 in if not (String.is_prefix s ~prefix:"operator<") && String.contains s '<' then
if String.is_prefix qual_name ~prefix:"std::operator<" then failwithf "Unexpected template in fuzzy qualified name %s." qual_name ) ;
String.drop_prefix qual_name operator_less_length
else qual_name
in
if String.contains filtered_qual_name '<' then
failwithf "Unexpected template in fuzzy qualified name %s." qual_name ;
of_qual_string qual_name of_qual_string qual_name
let of_fuzzy_qual_names fuzzy_qual_names = let of_fuzzy_qual_names fuzzy_qual_names =

@ -241,10 +241,15 @@ let use_jar_cache = true
let weak = "<\"Weak\">" let weak = "<\"Weak\">"
let whitelisted_cpp_methods = (* Whitelists for C++ library functions *)
[ "google::CheckNotNull"
let std_whitelisted_cpp_methods =
[ "std::back_inserter"
; "std::forward" ; "std::forward"
; "std::front_inserter"
; "std::get" ; "std::get"
; "std::inserter"
; "std::make_move_iterator"
; "std::make_pair" ; "std::make_pair"
; "std::max" ; "std::max"
; "std::min" ; "std::min"
@ -257,19 +262,62 @@ let whitelisted_cpp_methods =
; "std::operator>=" ; "std::operator>="
; "std::swap" ] ; "std::swap" ]
let whitelisted_cpp_classes = let libstdcxx_whitelisted_cpp_methods =
[ "__gnu_cxx::__normal_iterator" (* libstdc++ internal name of vector iterator *) [ "__gnu_cxx::operator!="
; "std::__less" ; "__gnu_cxx::operator<"
; "std::__wrap_iter" (* libc++ internal name of vector iterator *) ; "__gnu_cxx::operator<="
; "std::__get_pair" (* libc++ internal support class for std::get<std::pair> *) ; "__gnu_cxx::operator=="
; "std::__pair_get" (* libstdc++ internal support class for std::get<std::pair> *) ; "__gnu_cxx::operator>"
; "__gnu_cxx::operator>="
; "__gnu_cxx::operator+"
; "__gnu_cxx::operator-" ]
let libcxx_whitelisted_cpp_methods = []
let other_whitelisted_cpp_methods = ["google::CheckNotNull"]
let whitelisted_cpp_methods =
List.concat
[ std_whitelisted_cpp_methods
; libstdcxx_whitelisted_cpp_methods
; libcxx_whitelisted_cpp_methods
; other_whitelisted_cpp_methods ]
(* Whitelists for C++ library classes *)
let std_whitelisted_cpp_classes =
[ "std::back_insert_iterator"
; "std::equal_to" ; "std::equal_to"
; "std::front_insert_iterator"
; "std::greater" ; "std::greater"
; "std::greater_equal" ; "std::greater_equal"
; "std::insert_iterator"
; "std::less" ; "std::less"
; "std::less_equal" ; "std::less_equal"
; "std::move_iterator"
; "std::not_equal_to" ; "std::not_equal_to"
; "std::pair" ] ; "std::pair"
; "std::reverse_iterator" ]
let libstdcxx_whitelisted_cpp_classes =
(* libstdc++ internal support class for std::get<std::pair> *)
[ "__gnu_cxx::__normal_iterator" (* libstdc++ internal name of vector iterator *)
; "std::__pair_get" ]
let libcxx_whitelisted_cpp_classes =
(* libc++ internal support class for std::get<std::pair> *)
[ "std::__less"
; "std::__wrap_iter" (* libc++ internal name of vector iterator *)
; "std::__get_pair" ]
let other_whitelisted_cpp_classes = []
let whitelisted_cpp_classes =
List.concat
[ std_whitelisted_cpp_classes
; libstdcxx_whitelisted_cpp_classes
; libcxx_whitelisted_cpp_classes
; other_whitelisted_cpp_classes ]
type dynamic_dispatch_policy = [`None | `Interface | `Sound | `Lazy] type dynamic_dispatch_policy = [`None | `Interface | `Sound | `Lazy]

@ -9,7 +9,7 @@ TESTS_DIR = ../../..
ANALYZER = infer ANALYZER = infer
CLANG_OPTIONS = -x c++ -std=c++14 -isystem$(ROOT_DIR) -c CLANG_OPTIONS = -x c++ -std=c++1y -isystem$(ROOT_DIR) -c
INFER_OPTIONS = --ml-buckets cpp --no-filtering --debug-exceptions --project-root $(TESTS_DIR) \ INFER_OPTIONS = --ml-buckets cpp --no-filtering --debug-exceptions --project-root $(TESTS_DIR) \
--no-keep-going --pmd-xml --report-custom-error --no-keep-going --pmd-xml --report-custom-error
INFERPRINT_OPTIONS = --issues-tests INFERPRINT_OPTIONS = --issues-tests

@ -32,7 +32,6 @@ codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_from, 3, DIVIDE_BY_ZE
codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_to, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_to(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X] codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_to, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_to(),start of procedure X,return from a call to move::X_X,start of procedure X,return from a call to move::X_X]
codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null0_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null0_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull] codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null0_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null0_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull]
codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null1_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null1_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull] codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null1_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null1_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull]
codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null2_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null2_bad(),start of procedure pair::pairOfZeroNull(),return from a call to pair::pairOfZeroNull]
codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null3_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null3_bad(),start of procedure pair::pairOfZeroNull2(),return from a call to pair::pairOfZeroNull2] codetoanalyze/cpp/errors/models/pair.cpp, pair::deref_pair_null3_bad, 3, NULL_DEREFERENCE, [start of procedure pair::deref_pair_null3_bad(),start of procedure pair::pairOfZeroNull2(),return from a call to pair::pairOfZeroNull2]
codetoanalyze/cpp/errors/models/swap.cpp, swap_null_bad, 4, NULL_DEREFERENCE, [start of procedure swap_null_bad()] codetoanalyze/cpp/errors/models/swap.cpp, swap_null_bad, 4, NULL_DEREFERENCE, [start of procedure swap_null_bad()]
codetoanalyze/cpp/errors/models/throw_wrapper.cpp, nothrow_if_null_bad, 4, NULL_DEREFERENCE, [start of procedure nothrow_if_null_bad(),start of procedure get_null(),return from a call to get_null,Condition is true,start of procedure do_nothing(),return from a call to do_nothing] codetoanalyze/cpp/errors/models/throw_wrapper.cpp, nothrow_if_null_bad, 4, NULL_DEREFERENCE, [start of procedure nothrow_if_null_bad(),start of procedure get_null(),return from a call to get_null,Condition is true,start of procedure do_nothing(),return from a call to do_nothing]
@ -213,6 +212,10 @@ codetoanalyze/cpp/errors/vector/empty_access.cpp, vector_as_param_by_value_empty
codetoanalyze/cpp/errors/vector/empty_access.cpp, vector_as_param_clear, 3, EMPTY_VECTOR_ACCESS, [start of procedure vector_as_param_clear(),start of procedure vector_param_clear(),return from a call to vector_param_clear] codetoanalyze/cpp/errors/vector/empty_access.cpp, vector_as_param_clear, 3, EMPTY_VECTOR_ACCESS, [start of procedure vector_as_param_clear(),start of procedure vector_param_clear(),return from a call to vector_param_clear]
codetoanalyze/cpp/errors/vector/empty_access.cpp, vector_as_param_empty, 2, EMPTY_VECTOR_ACCESS, [start of procedure vector_as_param_empty(),start of procedure vector_param_access(),return from a call to vector_param_access] codetoanalyze/cpp/errors/vector/empty_access.cpp, vector_as_param_empty, 2, EMPTY_VECTOR_ACCESS, [start of procedure vector_as_param_empty(),start of procedure vector_param_access(),return from a call to vector_param_access]
codetoanalyze/cpp/errors/vector/iterator_access.cpp, iterator_access::possible_npe, 4, NULL_DEREFERENCE, [start of procedure iterator_access::possible_npe(),Condition is true,Condition is true,Condition is true] codetoanalyze/cpp/errors/vector/iterator_access.cpp, iterator_access::possible_npe, 4, NULL_DEREFERENCE, [start of procedure iterator_access::possible_npe(),Condition is true,Condition is true,Condition is true]
codetoanalyze/cpp/errors/vector/iterator_cmp.cpp, iterator_compare::empty_deref1_bad, 4, NULL_DEREFERENCE, [start of procedure iterator_compare::empty_deref1_bad(),start of procedure iterator_compare::is_empty(),return from a call to iterator_compare::is_empty,Condition is true]
codetoanalyze/cpp/errors/vector/iterator_cmp.cpp, iterator_compare::empty_deref2_bad, 4, NULL_DEREFERENCE, [start of procedure iterator_compare::empty_deref2_bad(),start of procedure iterator_compare::not_empty(),return from a call to iterator_compare::not_empty,Condition is false,Condition is true]
codetoanalyze/cpp/errors/vector/iterator_cmp.cpp, iterator_compare::not_empty_deref1_bad, 4, NULL_DEREFERENCE, [start of procedure iterator_compare::not_empty_deref1_bad(),Skipped call: function or method not found,start of procedure iterator_compare::is_empty(),return from a call to iterator_compare::is_empty,Condition is false,Condition is true]
codetoanalyze/cpp/errors/vector/iterator_cmp.cpp, iterator_compare::not_empty_deref2_bad, 4, NULL_DEREFERENCE, [start of procedure iterator_compare::not_empty_deref2_bad(),Skipped call: function or method not found,start of procedure iterator_compare::not_empty(),return from a call to iterator_compare::not_empty,Condition is true]
codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg2_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg2_null_deref()] codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg2_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg2_null_deref()]
codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg3_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg3_null_deref(),start of procedure derefFirstArg3()] codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg3_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg3_null_deref(),start of procedure derefFirstArg3()]
codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg_null_deref()] codetoanalyze/cpp/shared/attributes/annotate.cpp, derefFirstArg_null_deref, 2, NULL_DEREFERENCE, [start of procedure derefFirstArg_null_deref()]

@ -30,12 +30,6 @@ int deref_pair_null1_bad() {
return std::get<0>(p) + *std::get<1>(p); return std::get<0>(p) + *std::get<1>(p);
} }
int deref_pair_null2_bad() {
auto p = pairOfZeroNull();
// Should report an NPE here as p.second is NULL
return std::get<int>(p) + *std::get<int*>(p);
}
int deref_pair_null3_bad() { int deref_pair_null3_bad() {
auto p = pairOfZeroNull2(); auto p = pairOfZeroNull2();
// Should report an NPE here as p.second is NULL // Should report an NPE here as p.second is NULL

@ -0,0 +1,73 @@
/*
* Copyright (c) 2017 - 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.
*/
#include <vector>
namespace iterator_compare {
bool is_empty(const std::vector<int>& vec) { return vec.begin() == vec.end(); }
bool not_empty(const std::vector<int>& vec) { return vec.begin() != vec.end(); }
void empty_no_deref1_ok() {
int* p = nullptr;
std::vector<int> vec;
if (!is_empty(vec))
*p = 42;
}
void empty_no_deref2_ok() {
int* p = nullptr;
std::vector<int> vec;
if (not_empty(vec))
*p = 42;
}
void empty_deref1_bad() {
int* p = nullptr;
std::vector<int> vec;
if (is_empty(vec))
*p = 42;
}
void empty_deref2_bad() {
int* p = nullptr;
std::vector<int> vec;
if (!not_empty(vec))
*p = 42;
}
void not_empty_no_deref1_ok() {
int* p = nullptr;
std::vector<int> vec = {1, 2, 3, 4};
if (is_empty(vec))
*p = 42;
}
void not_empty_no_deref2_ok() {
int* p = nullptr;
std::vector<int> vec = {1, 2, 3, 4};
if (!not_empty(vec))
*p = 42;
}
void not_empty_deref1_bad() {
int* p = nullptr;
std::vector<int> vec = {1, 2, 3, 4};
if (!is_empty(vec))
*p = 42;
}
void not_empty_deref2_bad() {
int* p = nullptr;
std::vector<int> vec = {1, 2, 3, 4};
if (not_empty(vec))
*p = 42;
}
} // namespace iterator_compare
Loading…
Cancel
Save