diff --git a/infer/src/checkers/ThreadSafety.ml b/infer/src/checkers/ThreadSafety.ml index 4810c8048..b9eb69377 100644 --- a/infer/src/checkers/ThreadSafety.ml +++ b/infer/src/checkers/ThreadSafety.ml @@ -83,8 +83,9 @@ module TransferFunctions (CFG : ProcCfg.S) = struct | _ -> false let get_lock_model = - let is_std_mutex_lock = - let matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::mutex::lock"] in + let is_cpp_lock = + let matcher = QualifiedCppName.Match.of_fuzzy_qual_names [ + "std::mutex::lock"; "std::lock_guard::lock_guard"] in fun pname -> QualifiedCppName.Match.match_qualifiers matcher (Typ.Procname.get_qualifiers pname) and is_std_mutex_unlock = @@ -123,7 +124,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct | _ -> NoEffect end - | (Typ.Procname.ObjC_Cpp _ as pname) when is_std_mutex_lock pname -> + | (Typ.Procname.ObjC_Cpp _ as pname) when is_cpp_lock pname -> Lock | (Typ.Procname.ObjC_Cpp _ as pname) when is_std_mutex_unlock pname -> Unlock diff --git a/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp b/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp index 38ecc4e8a..cf151a33d 100644 --- a/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp +++ b/infer/tests/codetoanalyze/cpp/threadsafety/issues.exp @@ -3,3 +3,8 @@ codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get3, 0, THREAD_SAFETY_ codetoanalyze/cpp/threadsafety/basics.cpp, basics::Basic_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `suspiciously_read`,,access to `suspiciously_read`] codetoanalyze/cpp/threadsafety/basics_with_mutex.cpp, basics::BasicsWithHeader_get1, 0, THREAD_SAFETY_VIOLATION, [,access to `field_1`,,access to `field_1`] codetoanalyze/cpp/threadsafety/basics_with_mutex.cpp, basics::BasicsWithHeader_get2, 0, THREAD_SAFETY_VIOLATION, [,access to `field_2`,,access to `field_2`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get2, 3, THREAD_SAFETY_VIOLATION, [,access to `suspiciously_written`,,access to `suspiciously_written`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get3, 0, THREAD_SAFETY_VIOLATION, [,access to `not_guarded`,,access to `not_guarded`] +codetoanalyze/cpp/threadsafety/lock_guard.cpp, basics::LockGuard_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `suspiciously_read`,,access to `suspiciously_read`] +codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get3, 0, THREAD_SAFETY_VIOLATION, [,access to `not_guarded`,,access to `not_guarded`] +codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp, basics::LockGuardWithScope_get4, 0, THREAD_SAFETY_VIOLATION, [,access to `suspiciously_read`,,access to `suspiciously_read`] diff --git a/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard.cpp b/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard.cpp new file mode 100644 index 000000000..b143eb7ad --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard.cpp @@ -0,0 +1,51 @@ +/* + * 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 + +namespace basics { + +class LockGuard { + public: + LockGuard() {} + + void set(int new_value) { + not_guarded = new_value; + suspiciously_written = new_value; + std::lock_guard lock(mutex_); + well_guarded = new_value; + suspiciously_read = new_value; + } + + int get1() { + int result; + std::lock_guard lock(mutex_); + result = well_guarded; + return result; + } + + int get2() { + int result; + std::lock_guard lock(mutex_); + result = suspiciously_written; + return result; + } + + int get3() { return not_guarded; } + + int get4() { return suspiciously_read; } + + private: + int well_guarded; + int suspiciously_read; + int suspiciously_written; + int not_guarded; + std::mutex mutex_; +}; +} diff --git a/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp b/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp new file mode 100644 index 000000000..019338245 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/threadsafety/lock_guard_with_scope.cpp @@ -0,0 +1,58 @@ +/* + * 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 + +namespace basics { + +class LockGuardWithScope { + public: + LockGuardWithScope() {} + + void set(int new_value) { + { + std::lock_guard lock(mutex_); + well_guarded = new_value; + suspiciously_read = new_value; + } + + // FIXME: missing unlocks in destructors make the following accesses + // to be treated as protected + not_guarded = new_value; + suspiciously_written = new_value; + } + + int get1() { + int result; + std::lock_guard lock(mutex_); + result = well_guarded; + return result; + } + + int get2() { + int result; + std::lock_guard lock(mutex_); + // FIXME: It does not report due to missing unlocks in destructors + result = suspiciously_written; + return result; + } + + // FIXME: It reports due to missing unlocks in destructors + int get3() { return not_guarded; } + + int get4() { return suspiciously_read; } + + private: + int well_guarded; + int suspiciously_read; + int suspiciously_written; + int not_guarded; + std::mutex mutex_; +}; +}