diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 02182a00d..5cf299e55 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -250,14 +250,22 @@ let use_jar_cache = true let weak = "<\"Weak\">" let whitelisted_cpp_methods = - ["std::move"; "std::forward"; "std::min"; "std::max"; "std::swap"; "google::CheckNotNull"] + [ "google::CheckNotNull" + ; "std::forward" + ; "std::get" + ; "std::make_pair" + ; "std::max" + ; "std::min" + ; "std::move" + ; "std::swap" ] let whitelisted_cpp_classes = - (* libstdc++ internal name of vector iterator *) - [ "std::__less" - ; "std::__wrap_iter" - ; (* libc++ internal name of vector iterator *) - "__gnu_cxx::__normal_iterator" ] + [ "__gnu_cxx::__normal_iterator" (* libstdc++ internal name of vector iterator *) + ; "std::__less" + ; "std::__wrap_iter" (* libc++ internal name of vector iterator *) + ; "std::__get_pair" (* libc++ internal support class for std::get *) + ; "std::__pair_get" (* libstdc++ internal support class for std::get *) + ; "std::pair" ] type dynamic_dispatch_policy = [`None | `Interface | `Sound | `Lazy] diff --git a/infer/tests/codetoanalyze/cpp/errors/Makefile b/infer/tests/codetoanalyze/cpp/errors/Makefile index 1fbd051b5..372fcf073 100644 --- a/infer/tests/codetoanalyze/cpp/errors/Makefile +++ b/infer/tests/codetoanalyze/cpp/errors/Makefile @@ -9,7 +9,7 @@ TESTS_DIR = ../../.. ANALYZER = infer -CLANG_OPTIONS = -x c++ -std=c++11 -isystem$(ROOT_DIR) -c +CLANG_OPTIONS = -x c++ -std=c++14 -isystem$(ROOT_DIR) -c INFER_OPTIONS = --ml-buckets cpp --no-filtering --debug-exceptions --project-root $(TESTS_DIR) \ --no-failures-allowed --pmd-xml INFERPRINT_OPTIONS = --issues-tests diff --git a/infer/tests/codetoanalyze/cpp/errors/issues.exp b/infer/tests/codetoanalyze/cpp/errors/issues.exp index a8e52272c..37b3b7f82 100644 --- a/infer/tests/codetoanalyze/cpp/errors/issues.exp +++ b/infer/tests/codetoanalyze/cpp/errors/issues.exp @@ -18,6 +18,10 @@ codetoanalyze/cpp/errors/memory_leaks/object_leak.cpp, object_leak, 0, MEMORY_LE codetoanalyze/cpp/errors/memory_leaks/raii_malloc.cpp, memory_leak, 0, MEMORY_LEAK, [start of procedure memory_leak()] codetoanalyze/cpp/errors/models/move.cpp, move::div0_moved_from, 3, DIVIDE_BY_ZERO, [start of procedure move::div0_moved_from(),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_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/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/mutex/std_mutex.cpp, alarm1, 2, DOUBLE_LOCK, [start of procedure alarm1()] diff --git a/infer/tests/codetoanalyze/cpp/errors/models/pair.cpp b/infer/tests/codetoanalyze/cpp/errors/models/pair.cpp new file mode 100644 index 000000000..b47ab4423 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/errors/models/pair.cpp @@ -0,0 +1,53 @@ +/* + * 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 +#include // for std::get + +namespace pair { + +std::pair pairOfZeroNull() { + return std::pair(0, nullptr); +} + +std::pair pairOfZeroNull2() { return std::make_pair(0, nullptr); } + +int deref_pair_null0_bad() { + auto p = pairOfZeroNull(); + // Should report an NPE here as p.second is NULL + return p.first + *p.second; +} + +int deref_pair_null1_bad() { + auto p = pairOfZeroNull(); + // Should report an NPE here as p.second is NULL + 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(p) + *std::get(p); +} + +int deref_pair_null3_bad() { + auto p = pairOfZeroNull2(); + // Should report an NPE here as p.second is NULL + return p.first + *p.second; +} + +int deref_pair_null_guard_ok() { + auto p = pairOfZeroNull(); + if (p.second != nullptr) { + // Should not report an NPE here as p.second is guarded + return p.first + *p.second; + } + return 0; +} +}