diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index 28a9f10c4..fa8b85486 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -265,7 +265,10 @@ let std_whitelisted_cpp_classes = ; "std::move_iterator" ; "std::not_equal_to" ; "std::pair" - ; "std::reverse_iterator" ] + ; "std::reverse_iterator" + ; "std::shared_ptr" + ; "std::__shared_ptr" + ; "std::__shared_ptr_access" ] let libstdcxx_whitelisted_cpp_classes = diff --git a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp index 6cf893eb2..c5aef8f86 100644 --- a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp +++ b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -#include #include #include "main.h" @@ -16,7 +15,6 @@ int main() { internal::fun(1); // internal::fun definition should be translated internal_exclude::fun(1); // internal_exclude::fun shouldn't be translated external::fun(1); // external::fun definition shouldn't be translated - std::shared_ptr x; // shared_ptr::shared_ptr model should be translated std::string s("1234"); // string::string shouldn't be translated (there is no // model for it) } diff --git a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp.dot b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp.dot index 10f88492d..1139ce9c4 100644 --- a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp.dot +++ b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main.cpp.dot @@ -15,37 +15,33 @@ digraph cfg { "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_4" -> "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_2" ; -"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> x:std::shared_ptr \n " color=yellow style=filled] +"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> \n " color=yellow style=filled] - "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_8" ; + "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "main.fad58de7366495db4650cfefac2fcd61_2" [label="2: Exit main \n " color=yellow style=filled] -"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 22, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 22, column 1]\n _=*&x:std::shared_ptr [line 22, column 1]\n n$3=_fun_std::shared_ptr::~shared_ptr(&x:std::shared_ptr*) injected [line 22, column 1]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 20, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 20, column 1]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; -"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 20, column 3]\n n$5=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 20, column 15]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 18, column 3]\n n$3=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 18, column 15]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_4" -> "main.fad58de7366495db4650cfefac2fcd61_3" ; -"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: DeclStmt \n VARIABLE_DECLARED(x:std::shared_ptr); [line 19, column 3]\n n$6=_fun_std::shared_ptr::shared_ptr(&x:std::shared_ptr*) [line 19, column 24]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: Call _fun_external::fun \n n$4=_fun_external::fun(1:int) [line 17, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; -"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_external::fun \n n$7=_fun_external::fun(1:int) [line 18, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_internal_exclude::fun \n n$5=_fun_internal_exclude::fun(1:int) [line 16, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_6" -> "main.fad58de7366495db4650cfefac2fcd61_5" ; -"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal_exclude::fun \n n$8=_fun_internal_exclude::fun(1:int) [line 17, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal::fun \n n$6=_fun_internal::fun(1:int) [line 15, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_7" -> "main.fad58de7366495db4650cfefac2fcd61_6" ; -"main.fad58de7366495db4650cfefac2fcd61_8" [label="8: Call _fun_internal::fun \n n$9=_fun_internal::fun(1:int) [line 16, column 3]\n " shape="box"] - - - "main.fad58de7366495db4650cfefac2fcd61_8" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "unused_deref_in_header#15260603227785084028.ec2f844a26989dc35e9856ba0d7a485b_1" [label="1: Start unused_deref_in_header\nFormals: a:int*\nLocals: x:int \n " color=yellow style=filled] diff --git a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_root.cpp.dot b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_root.cpp.dot index 10f88492d..1139ce9c4 100644 --- a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_root.cpp.dot +++ b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_root.cpp.dot @@ -15,37 +15,33 @@ digraph cfg { "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_4" -> "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_2" ; -"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> x:std::shared_ptr \n " color=yellow style=filled] +"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> \n " color=yellow style=filled] - "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_8" ; + "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "main.fad58de7366495db4650cfefac2fcd61_2" [label="2: Exit main \n " color=yellow style=filled] -"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 22, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 22, column 1]\n _=*&x:std::shared_ptr [line 22, column 1]\n n$3=_fun_std::shared_ptr::~shared_ptr(&x:std::shared_ptr*) injected [line 22, column 1]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 20, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 20, column 1]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; -"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 20, column 3]\n n$5=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 20, column 15]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 18, column 3]\n n$3=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 18, column 15]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_4" -> "main.fad58de7366495db4650cfefac2fcd61_3" ; -"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: DeclStmt \n VARIABLE_DECLARED(x:std::shared_ptr); [line 19, column 3]\n n$6=_fun_std::shared_ptr::shared_ptr(&x:std::shared_ptr*) [line 19, column 24]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: Call _fun_external::fun \n n$4=_fun_external::fun(1:int) [line 17, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; -"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_external::fun \n n$7=_fun_external::fun(1:int) [line 18, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_internal_exclude::fun \n n$5=_fun_internal_exclude::fun(1:int) [line 16, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_6" -> "main.fad58de7366495db4650cfefac2fcd61_5" ; -"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal_exclude::fun \n n$8=_fun_internal_exclude::fun(1:int) [line 17, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal::fun \n n$6=_fun_internal::fun(1:int) [line 15, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_7" -> "main.fad58de7366495db4650cfefac2fcd61_6" ; -"main.fad58de7366495db4650cfefac2fcd61_8" [label="8: Call _fun_internal::fun \n n$9=_fun_internal::fun(1:int) [line 16, column 3]\n " shape="box"] - - - "main.fad58de7366495db4650cfefac2fcd61_8" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "unused_deref_in_header#15260603227785084028.ec2f844a26989dc35e9856ba0d7a485b_1" [label="1: Start unused_deref_in_header\nFormals: a:int*\nLocals: x:int \n " color=yellow style=filled] diff --git a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_symlink.cpp.dot b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_symlink.cpp.dot index 10f88492d..1139ce9c4 100644 --- a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_symlink.cpp.dot +++ b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_default_symlink.cpp.dot @@ -15,37 +15,33 @@ digraph cfg { "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_4" -> "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_2" ; -"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> x:std::shared_ptr \n " color=yellow style=filled] +"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> \n " color=yellow style=filled] - "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_8" ; + "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "main.fad58de7366495db4650cfefac2fcd61_2" [label="2: Exit main \n " color=yellow style=filled] -"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 22, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 22, column 1]\n _=*&x:std::shared_ptr [line 22, column 1]\n n$3=_fun_std::shared_ptr::~shared_ptr(&x:std::shared_ptr*) injected [line 22, column 1]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 20, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 20, column 1]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; -"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 20, column 3]\n n$5=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 20, column 15]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 18, column 3]\n n$3=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 18, column 15]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_4" -> "main.fad58de7366495db4650cfefac2fcd61_3" ; -"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: DeclStmt \n VARIABLE_DECLARED(x:std::shared_ptr); [line 19, column 3]\n n$6=_fun_std::shared_ptr::shared_ptr(&x:std::shared_ptr*) [line 19, column 24]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: Call _fun_external::fun \n n$4=_fun_external::fun(1:int) [line 17, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; -"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_external::fun \n n$7=_fun_external::fun(1:int) [line 18, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_internal_exclude::fun \n n$5=_fun_internal_exclude::fun(1:int) [line 16, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_6" -> "main.fad58de7366495db4650cfefac2fcd61_5" ; -"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal_exclude::fun \n n$8=_fun_internal_exclude::fun(1:int) [line 17, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal::fun \n n$6=_fun_internal::fun(1:int) [line 15, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_7" -> "main.fad58de7366495db4650cfefac2fcd61_6" ; -"main.fad58de7366495db4650cfefac2fcd61_8" [label="8: Call _fun_internal::fun \n n$9=_fun_internal::fun(1:int) [line 16, column 3]\n " shape="box"] - - - "main.fad58de7366495db4650cfefac2fcd61_8" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "unused_deref_in_header#15260603227785084028.ec2f844a26989dc35e9856ba0d7a485b_1" [label="1: Start unused_deref_in_header\nFormals: a:int*\nLocals: x:int \n " color=yellow style=filled] diff --git a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_symlink.cpp.dot b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_symlink.cpp.dot index 10f88492d..1139ce9c4 100644 --- a/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_symlink.cpp.dot +++ b/infer/tests/build_systems/codetoanalyze/clang_translation/src/main_symlink.cpp.dot @@ -15,37 +15,33 @@ digraph cfg { "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_4" -> "fun#internal#3922054098004616643.55c3f2ad552457f847bc1570fce79224_2" ; -"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> x:std::shared_ptr \n " color=yellow style=filled] +"main.fad58de7366495db4650cfefac2fcd61_1" [label="1: Start main\nFormals: \nLocals: s:std::basic_string,std::allocator> \n " color=yellow style=filled] - "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_8" ; + "main.fad58de7366495db4650cfefac2fcd61_1" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "main.fad58de7366495db4650cfefac2fcd61_2" [label="2: Exit main \n " color=yellow style=filled] -"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 22, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 22, column 1]\n _=*&x:std::shared_ptr [line 22, column 1]\n n$3=_fun_std::shared_ptr::~shared_ptr(&x:std::shared_ptr*) injected [line 22, column 1]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_3" [label="3: Destruction(Scope) \n _=*&s:std::basic_string,std::allocator> [line 20, column 1]\n n$1=_fun_std::basic_string,std::allocator>::~basic_string(&s:std::basic_string,std::allocator>*) injected [line 20, column 1]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_3" -> "main.fad58de7366495db4650cfefac2fcd61_2" ; -"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 20, column 3]\n n$5=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 20, column 15]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_4" [label="4: DeclStmt \n VARIABLE_DECLARED(s:std::basic_string,std::allocator>); [line 18, column 3]\n n$3=_fun_std::basic_string,std::allocator>::basic_string(&s:std::basic_string,std::allocator>*,\"1234\":char const *) [line 18, column 15]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_4" -> "main.fad58de7366495db4650cfefac2fcd61_3" ; -"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: DeclStmt \n VARIABLE_DECLARED(x:std::shared_ptr); [line 19, column 3]\n n$6=_fun_std::shared_ptr::shared_ptr(&x:std::shared_ptr*) [line 19, column 24]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_5" [label="5: Call _fun_external::fun \n n$4=_fun_external::fun(1:int) [line 17, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; -"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_external::fun \n n$7=_fun_external::fun(1:int) [line 18, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_6" [label="6: Call _fun_internal_exclude::fun \n n$5=_fun_internal_exclude::fun(1:int) [line 16, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_6" -> "main.fad58de7366495db4650cfefac2fcd61_5" ; -"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal_exclude::fun \n n$8=_fun_internal_exclude::fun(1:int) [line 17, column 3]\n " shape="box"] +"main.fad58de7366495db4650cfefac2fcd61_7" [label="7: Call _fun_internal::fun \n n$6=_fun_internal::fun(1:int) [line 15, column 3]\n " shape="box"] "main.fad58de7366495db4650cfefac2fcd61_7" -> "main.fad58de7366495db4650cfefac2fcd61_6" ; -"main.fad58de7366495db4650cfefac2fcd61_8" [label="8: Call _fun_internal::fun \n n$9=_fun_internal::fun(1:int) [line 16, column 3]\n " shape="box"] - - - "main.fad58de7366495db4650cfefac2fcd61_8" -> "main.fad58de7366495db4650cfefac2fcd61_7" ; "unused_deref_in_header#15260603227785084028.ec2f844a26989dc35e9856ba0d7a485b_1" [label="1: Start unused_deref_in_header\nFormals: a:int*\nLocals: x:int \n " color=yellow style=filled] diff --git a/infer/tests/codetoanalyze/cpp/biabduction/issues.exp b/infer/tests/codetoanalyze/cpp/biabduction/issues.exp index 906769c43..7a25f9b97 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/issues.exp +++ b/infer/tests/codetoanalyze/cpp/biabduction/issues.exp @@ -65,12 +65,13 @@ codetoanalyze/cpp/biabduction/npe/cancellation.cpp, cancellation_test::size_zero codetoanalyze/cpp/biabduction/npe/cancellation.cpp, cancellation_test::size_zero_deref_iter2_bad, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure cancellation_test::size_zero_deref_iter2_bad(),start of procedure cancellation_test::is_size_zero_iter(),start of procedure begin_iter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::Test::begin_iter,start of procedure end_iter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::Test::end_iter,start of procedure cancellation_test::operator==(),Condition is true,return from a call to cancellation_test::operator==,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::is_size_zero_iter,Taking true branch] codetoanalyze/cpp/biabduction/npe/cancellation.cpp, cancellation_test::size_zero_deref_iter_bad, 4, NULL_DEREFERENCE, B1, ERROR, [start of procedure cancellation_test::size_zero_deref_iter_bad(),start of procedure cancellation_test::is_size_zero_iter(),start of procedure begin_iter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::Test::begin_iter,start of procedure end_iter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,start of procedure TestIter,return from a call to cancellation_test::TestIter::TestIter,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::Test::end_iter,start of procedure cancellation_test::operator==(),Condition is true,return from a call to cancellation_test::operator==,Skipping ~TestIter: method has no implementation,return from a call to cancellation_test::is_size_zero_iter,Taking true branch] codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp, npe_added_to_b1::causes_npe_person_bad, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure npe_added_to_b1::causes_npe_person_bad(),start of procedure Person,return from a call to npe_added_to_b1::Person::Person,start of procedure npe_added_to_b1::deref_person()] +codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp, npe_added_to_b1::shared_ptr_uninit_deref_bad, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure npe_added_to_b1::shared_ptr_uninit_deref_bad(),start of procedure npe_added_to_b1::deref_ref()] codetoanalyze/cpp/biabduction/npe/null_returned_by_method.cpp, testNullDeref, 3, NULL_DEREFERENCE, B2, ERROR, [start of procedure testNullDeref(),Taking true branch,start of procedure getNull,return from a call to XFactory::getNull] codetoanalyze/cpp/biabduction/npe/object_deref.cpp, object_deref::derefNullField, 2, NULL_DEREFERENCE, B1, ERROR, [start of procedure object_deref::derefNullField(),start of procedure object_deref::getNull(),return from a call to object_deref::getNull] -codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, ERROR_FP_skip_then_split_case_bad, 3, Cannot_star, no_bucket, ERROR, [start of procedure ERROR_FP_skip_then_split_case_bad(),Skipping std::make_shared(): method has no implementation,Skipping ~shared_ptr: method has no implementation,Skipping skip_no_const(): method has no implementation] -codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, ERROR_const_skip2_then_split_case_ok, 3, Cannot_star, no_bucket, ERROR, [start of procedure ERROR_const_skip2_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping ~shared_ptr: method has no implementation,Skipping skip_const2(): method has no implementation] -codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, ERROR_const_skip_then_split_case_ok, 3, Cannot_star, no_bucket, ERROR, [start of procedure ERROR_const_skip_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping ~shared_ptr: method has no implementation,Skipping skip_const(): method has no implementation] -codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, ERROR_typedef_skip_then_split_case_ok, 3, Cannot_star, no_bucket, ERROR, [start of procedure ERROR_typedef_skip_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping ~shared_ptr: method has no implementation,Skipping skip_typedef(): method has no implementation] +codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, FP_const_skip2_then_split_case_ok, 4, NULL_DEREFERENCE, B5, ERROR, [start of procedure FP_const_skip2_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping skip_const2(): method has no implementation,start of procedure test_pointer(),Taking false branch,return from a call to test_pointer] +codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, FP_const_skip_then_split_case_ok, 5, NULL_DEREFERENCE, B5, ERROR, [start of procedure FP_const_skip_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping skip_const(): method has no implementation,start of procedure test_pointer(),Taking false branch,return from a call to test_pointer] +codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, FP_skip_then_split_case_bad, 5, NULL_DEREFERENCE, B5, ERROR, [start of procedure FP_skip_then_split_case_bad(),Skipping std::make_shared(): method has no implementation,Skipping skip_no_const(): method has no implementation,start of procedure test_pointer(),Taking false branch,return from a call to test_pointer] +codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp, FP_typedef_skip_then_split_case_ok, 4, NULL_DEREFERENCE, B5, ERROR, [start of procedure FP_typedef_skip_then_split_case_ok(),Skipping std::make_shared(): method has no implementation,Skipping skip_typedef(): method has no implementation,start of procedure test_pointer(),Taking false branch,return from a call to test_pointer] codetoanalyze/cpp/biabduction/numeric/min_max.cpp, max_X_inv_div0, 2, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure max_X_inv_div0(),start of procedure X_inv,return from a call to X_inv::X_inv,start of procedure X_inv,return from a call to X_inv::X_inv] codetoanalyze/cpp/biabduction/numeric/min_max.cpp, max_int_div0, 0, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure max_int_div0()] codetoanalyze/cpp/biabduction/numeric/min_max.cpp, min_X_div0, 2, DIVIDE_BY_ZERO, no_bucket, ERROR, [start of procedure min_X_div0(),start of procedure X,return from a call to X::X,start of procedure X,return from a call to X::X] @@ -79,18 +80,21 @@ codetoanalyze/cpp/biabduction/overwrite_attribute/main.cpp, testSetIntValue, 3, codetoanalyze/cpp/biabduction/pointers/unintialized.cpp, known_ctor_dangling_bad, 2, DANGLING_POINTER_DEREFERENCE, no_bucket, ERROR, [start of procedure known_ctor_dangling_bad(),start of procedure TestDangling,return from a call to TestDangling::TestDangling] codetoanalyze/cpp/biabduction/pointers/unintialized.cpp, uninitialized_dangling_bad, 2, DANGLING_POINTER_DEREFERENCE, no_bucket, ERROR, [start of procedure uninitialized_dangling_bad()] codetoanalyze/cpp/biabduction/resource_leaks/raii.cpp, resource_leak, 7, RESOURCE_LEAK, no_bucket, ERROR, [start of procedure resource_leak(),Taking false branch] +codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp, test_const3_bad, 3, NULL_DEREFERENCE, B5, ERROR, [start of procedure test_const3_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp, test_const4_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure test_const4_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp, test_volatile3_bad, 3, NULL_DEREFERENCE, B5, ERROR, [start of procedure test_volatile3_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp, test_volatile4_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure test_volatile4_bad()] codetoanalyze/cpp/biabduction/smart_ptr/deref_after_move_example.cpp, deref_after_mode_example::Person::Person, 3, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure Person,Skipping unique_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::ERROR_shared_ptr_check_notnull_ok, 2, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr::ERROR_shared_ptr_check_notnull_ok(),Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::ERROR_shared_ptr_check_null_ok, 2, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr::ERROR_shared_ptr_check_null_ok(),Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FN_reset_ptr_null_deref2_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FN_reset_ptr_null_deref2_bad(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FN_reset_ptr_null_deref2_bad, 2, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FN_reset_ptr_null_deref2_bad(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation,Skipping reset: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FN_reset_ptr_null_deref_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FN_reset_ptr_null_deref_bad(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FN_shared_ptr_assign_null_deref_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FN_shared_ptr_assign_null_deref_bad(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FN_shared_ptr_move_null_deref_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FN_shared_ptr_move_null_deref_bad(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FP_reset_ptr_deref2_ok, 3, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FP_reset_ptr_deref2_ok(),Skipping shared_ptr: method has no implementation,Skipping reset: method has no implementation,Skipping reset: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FP_reset_ptr_deref_ok, 2, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FP_reset_ptr_deref_ok(),Skipping shared_ptr: method has no implementation,Skipping reset: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FP_shared_ptr_assign_deref_ok, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FP_shared_ptr_assign_deref_ok(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] -codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::FP_shared_ptr_copy_deref_ok, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure shared_ptr::FP_shared_ptr_copy_deref_ok(),Skipping __nat: method has no implementation,Skipping shared_ptr: method has no implementation] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::ERROR_aliasing_construct_from_external, 4, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr_constructors::ERROR_aliasing_construct_from_external(),Skipping shared_ptr_constructors::external_def(): method has no implementation,Taking false branch] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::ERROR_aliasing_construct_from_internal, 4, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr_constructors::ERROR_aliasing_construct_from_internal(),start of procedure shared_ptr_constructors::internal_null_def(),Skipping shared_ptr_constructors::external_def(): method has no implementation,return from a call to shared_ptr_constructors::internal_null_def,Taking false branch] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::ERROR_getFromDerived2, 2, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr_constructors::ERROR_getFromDerived2(),Skipping __nat: method has no implementation,Skipping __nat: method has no implementation,Skipping __nat: method has no implementation,Skipping __nat: method has no implementation] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::ERROR_getFromDerived3, 3, Cannot_star, no_bucket, ERROR, [start of procedure shared_ptr_constructors::ERROR_getFromDerived3(),Skipping __nat: method has no implementation,Skipping __nat: method has no implementation] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::empty_ptr_deref_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::empty_ptr_deref_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref2_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::empty_ptr_field_deref2_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::empty_ptr_field_deref_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::empty_ptr_method_deref_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::empty_ptr_method_deref_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::nullptr_ptr_deref_bad, 2, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::nullptr_ptr_deref_bad()] +codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp, shared_ptr::shared_ptr_copy_null_deref_bad, 3, NULL_DEREFERENCE, B5, ERROR, [start of procedure shared_ptr::shared_ptr_copy_null_deref_bad()] codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FN_FP_reset_ptr_null_deref2_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::FN_FP_reset_ptr_null_deref2_bad(),Skipping unique_ptr: method has no implementation] codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FN_FP_reset_ptr_null_deref2_bad, 2, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::FN_FP_reset_ptr_null_deref2_bad(),Skipping unique_ptr: method has no implementation,Skipping reset: method has no implementation] codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FN_FP_reset_ptr_null_deref_bad, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::FN_FP_reset_ptr_null_deref_bad(),Skipping unique_ptr: method has no implementation] @@ -100,6 +104,7 @@ codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FP_res codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FP_reset_ptr_deref_ok, 2, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::FP_reset_ptr_deref_ok(),Skipping unique_ptr: method has no implementation,Skipping reset: method has no implementation] codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::FP_unique_ptr_move_deref_ok, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::FP_unique_ptr_move_deref_ok(),Skipping unique_ptr: method has no implementation] codetoanalyze/cpp/biabduction/smart_ptr/unique_ptr_deref.cpp, unique_ptr::unique_ptr_assign_deref_ok, 1, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure unique_ptr::unique_ptr_assign_deref_ok(),Skipping unique_ptr: method has no implementation] +codetoanalyze/cpp/biabduction/smart_ptr/weak_ptr_compil.cpp, weak_ptr_lock_repro_small::ERROR_foo, 3, Cannot_star, no_bucket, ERROR, [start of procedure weak_ptr_lock_repro_small::ERROR_foo(),Skipping lock: method has no implementation,start of procedure weak_ptr_lock_repro_small::joinT(),return from a call to weak_ptr_lock_repro_small::joinT] codetoanalyze/cpp/biabduction/static_local/nonstatic_local_bad.cpp, nonstatic_local_caller, 2, DANGLING_POINTER_DEREFERENCE, no_bucket, ERROR, [start of procedure nonstatic_local_caller(),start of procedure nonstatic_local_bad(),return from a call to nonstatic_local_bad] codetoanalyze/cpp/biabduction/subtyping/cast_with_enforce.cpp, cast_with_enforce::cast_with_npe, 3, NULL_DEREFERENCE, B1, ERROR, [start of procedure cast_with_enforce::cast_with_npe(),start of procedure Base,return from a call to cast_with_enforce::Base::Base] codetoanalyze/cpp/biabduction/subtyping/dynamic_cast.cpp, dynamic__cast::rightPointerCast, 4, BIABDUCTION_MEMORY_LEAK, CPP, ERROR, [start of procedure dynamic__cast::rightPointerCast(),start of procedure Derived,start of procedure Base,return from a call to dynamic__cast::Base::Base,return from a call to dynamic__cast::Derived::Derived,Taking true branch] diff --git a/infer/tests/codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp b/infer/tests/codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp index b271e5ddd..4629c5582 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/npe/npe_added_to_b1.cpp @@ -11,7 +11,7 @@ namespace npe_added_to_b1 { int deref_ref(std::shared_ptr& p) { return *p; } -int FN_shared_ptr_uninit_deref_bad() { +int shared_ptr_uninit_deref_bad() { std::shared_ptr x; return deref_ref(x); } diff --git a/infer/tests/codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp b/infer/tests/codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp index 47ed5137b..1561a1685 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/npe/skip_function_with_const_formals.cpp @@ -25,7 +25,7 @@ void test_pointer(const std::shared_ptr& foo) { } } -void ERROR_FP_skip_then_split_case_bad() { +void FP_skip_then_split_case_bad() { auto foo = std::make_shared(); skip_no_const(foo); // Infer havocs foo here since it's not const test_pointer(foo); // this call creates a case split, foo can be null in one @@ -33,26 +33,26 @@ void ERROR_FP_skip_then_split_case_bad() { foo->f = 12; // error } -void ERROR_const_skip_then_split_case_ok() { +void FP_const_skip_then_split_case_ok() { auto foo = std::make_shared(); skip_const(foo); // Infer shouldn't havoc foo here since it's const... test_pointer(foo); /* ...so foo cannot be null here, even if there is an explicit null post... */ - foo->f = 12; // no error + foo->f = 12; // error } // same as above but make sure infer pinpoints the correct const argument -void ERROR_const_skip2_then_split_case_ok() { +void FP_const_skip2_then_split_case_ok() { auto foo = std::make_shared(); skip_const2(0, foo, 0, 0); test_pointer(foo); - foo->f = 12; // no error + foo->f = 12; // error } // same as above but hide the type under a typedef -void ERROR_typedef_skip_then_split_case_ok() { +void FP_typedef_skip_then_split_case_ok() { auto foo = std::make_shared(); skip_typedef(foo); test_pointer(foo); - foo->f = 12; // no error + foo->f = 12; // error } diff --git a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp index f0a353738..ab25b060e 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/const_volatile_type.cpp @@ -18,13 +18,13 @@ int FN_test_volatile2_bad() { return *x; } -int FN_test_volatile3_bad() { +int test_volatile3_bad() { std::shared_ptr x; std::shared_ptr y = std::move(x); return *y; } -int FN_test_volatile4_bad() { +int test_volatile4_bad() { std::shared_ptr x; return *x; } @@ -40,13 +40,13 @@ int FN_test_const2_bad() { return *x; } -int FN_test_const3_bad() { +int test_const3_bad() { std::shared_ptr x; std::shared_ptr y = std::move(x); return *y; } -int FN_test_const4_bad() { +int test_const4_bad() { std::shared_ptr x; return *x; } diff --git a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp index 4ed65f55c..db5acc4e6 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_constructors.cpp @@ -30,12 +30,12 @@ std::shared_ptr getFromDerived1(Derived* d) { return std::shared_ptr(d); } -std::shared_ptr getFromDerived2(Derived* d) { +std::shared_ptr ERROR_getFromDerived2(Derived* d) { std::shared_ptr sd(d); return std::shared_ptr(sd); } -std::shared_ptr getFromDerived3(Derived* d) { +std::shared_ptr ERROR_getFromDerived3(Derived* d) { std::shared_ptr sd(d); std::shared_ptr result; result = sd; // assignment operator @@ -55,11 +55,11 @@ void FN_get_from_derived1_nullptr_deref_bad() { } void FN_get_from_derived2_nullptr_deref_bad() { - Base b = *(getFromDerived2(nullptr)); + Base b = *(ERROR_getFromDerived2(nullptr)); } void FN_get_from_derived3_nullptr_deref_bad() { - Base b = *(getFromDerived3(nullptr)); + Base b = *(ERROR_getFromDerived3(nullptr)); } void FN_get_from_base1_null_f1_deref_bad() { @@ -93,7 +93,7 @@ void FN_get_from_derived2_null_f1_deref_bad() { Derived b; int v; b.f1 = &v; - std::shared_ptr p = getFromDerived2(&b); + std::shared_ptr p = ERROR_getFromDerived2(&b); b.f1 = nullptr; int r = *(p->f1); } @@ -102,7 +102,7 @@ void FN_get_from_derived3_null_f1_deref_bad() { Derived b; int v; b.f1 = &v; - std::shared_ptr p = getFromDerived3(&b); + std::shared_ptr p = ERROR_getFromDerived3(&b); b.f1 = nullptr; int r = *(p->f1); } @@ -125,13 +125,13 @@ std::shared_ptr internal_null_def() { return r; } -std::shared_ptr aliasing_construct_from_external() { +std::shared_ptr ERROR_aliasing_construct_from_external() { auto p = external_def(); if (!p) throw std::logic_error("Suppress NULL"); return {p, p->a}; } -std::shared_ptr aliasing_construct_from_internal() { +std::shared_ptr ERROR_aliasing_construct_from_internal() { auto p = internal_null_def(); if (!p) throw std::logic_error("Suppress NULL"); @@ -139,13 +139,13 @@ std::shared_ptr aliasing_construct_from_internal() { } void aliasing_member_not_null_ok() { - auto q = aliasing_construct_from_external(); + auto q = ERROR_aliasing_construct_from_external(); // q is unknown here so we should not report null deref // Also we should not report dangling pointer because q is still alive q->baz(); } void aliasing_member_null_bad() { - auto q = aliasing_construct_from_internal(); + auto q = ERROR_aliasing_construct_from_internal(); // q is known here so we should report null deref // Also we should not report dangling pointer because q is still alive q->baz(); diff --git a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp index fc3cd3619..2225e1c89 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/shared_ptr_deref.cpp @@ -24,27 +24,27 @@ int empty_ptr_access() { return 0; } -int FN_empty_ptr_deref_bad() { +int empty_ptr_deref_bad() { std::shared_ptr x; return *x; } -int FN_nullptr_ptr_deref_bad() { +int nullptr_ptr_deref_bad() { std::shared_ptr x(nullptr); return *x; } -int FN_empty_ptr_field_deref_bad() { +int empty_ptr_field_deref_bad() { std::shared_ptr x; return x.get()->field; } -int FN_empty_ptr_field_deref2_bad() { +int empty_ptr_field_deref2_bad() { std::shared_ptr x; return x->field; } -int FN_empty_ptr_method_deref_bad() { +int empty_ptr_method_deref_bad() { std::shared_ptr x; return x->get(); } @@ -62,20 +62,20 @@ int FN_reset_ptr_null_deref2_bad() { return *x; } -int FP_reset_ptr_deref_ok() { +int reset_ptr_deref_ok() { std::shared_ptr x; x.reset(new int); return *x; } -int FP_reset_ptr_deref2_ok() { +int reset_ptr_deref2_ok() { std::shared_ptr x; x.reset(); x.reset(new int); return *x; } -int FN_shared_ptr_copy_null_deref_bad() { +int shared_ptr_copy_null_deref_bad() { std::shared_ptr p1; std::shared_ptr p2 = p1; return *p2; @@ -110,7 +110,6 @@ int FN_shared_ptr_move_null_deref_bad() { return *p1; } -// Cannot_star int ERROR_shared_ptr_check_null_ok() { std::shared_ptr p; if (p == nullptr) @@ -118,8 +117,7 @@ int ERROR_shared_ptr_check_null_ok() { return *p; } -// Cannot_star -int ERROR_shared_ptr_check_notnull_ok() { +int shared_ptr_check_notnull_ok() { std::shared_ptr p; if (p != nullptr) return *p; diff --git a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/weak_ptr_compil.cpp b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/weak_ptr_compil.cpp index d2fc07650..7c3fab838 100644 --- a/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/weak_ptr_compil.cpp +++ b/infer/tests/codetoanalyze/cpp/biabduction/smart_ptr/weak_ptr_compil.cpp @@ -19,7 +19,8 @@ std::shared_ptr joinT(std::shared_ptr x) { return x; }; -void foo(std::weak_ptr p) { +// cannot star +void ERROR_foo(std::weak_ptr p) { auto self = p.lock(); std::shared_ptr x = joinT(self); } diff --git a/infer/tests/codetoanalyze/cpp/pulse/const_volatile_type.cpp b/infer/tests/codetoanalyze/cpp/pulse/const_volatile_type.cpp new file mode 100644 index 000000000..ab25b060e --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/const_volatile_type.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +int FN_test_volatile1_bad() { + std::unique_ptr x; + std::unique_ptr y = std::move(x); + return *y; +} + +int FN_test_volatile2_bad() { + std::unique_ptr x; + return *x; +} + +int test_volatile3_bad() { + std::shared_ptr x; + std::shared_ptr y = std::move(x); + return *y; +} + +int test_volatile4_bad() { + std::shared_ptr x; + return *x; +} + +int FN_test_const1_bad() { + std::unique_ptr x; + std::unique_ptr y = std::move(x); + return *y; +} + +int FN_test_const2_bad() { + std::unique_ptr x; + return *x; +} + +int test_const3_bad() { + std::shared_ptr x; + std::shared_ptr y = std::move(x); + return *y; +} + +int test_const4_bad() { + std::shared_ptr x; + return *x; +} diff --git a/infer/tests/codetoanalyze/cpp/pulse/deref_after_move_example.cpp b/infer/tests/codetoanalyze/cpp/pulse/deref_after_move_example.cpp new file mode 100644 index 000000000..b06a88acb --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/deref_after_move_example.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace deref_after_mode_example { + +struct Person { + // memory leak FP on Person::Person() because unique_ptr constructor is + // unknown + std::unique_ptr age{new int(35)}; + std::unique_ptr move_age() { return std::move(age); } + int access_age() { return *age; } +}; + +int FN_deref_after_move_bad() { + Person p; + auto x = p.move_age(); + *x; + return p.access_age(); +} + +int deref_ok() { + Person p; + return p.access_age(); +} + +int deref_after_move_ok() { + Person p; + auto x = p.move_age(); + return *x; +} +} // namespace deref_after_mode_example diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp b/infer/tests/codetoanalyze/cpp/pulse/issues.exp index b4e89a417..80716f05e 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp @@ -29,6 +29,10 @@ codetoanalyze/cpp/pulse/conditional_temporaries.cpp, condtemp::FP_track_copy_ope codetoanalyze/cpp/pulse/conditional_temporaries.cpp, condtemp::X::__infer_inner_destructor_~X, 1, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,source of the null value part of the trace starts here,is the null pointer,null pointer dereference part of the trace starts here,parameter `this` of condtemp::X::__infer_inner_destructor_~X,when calling `condtemp::X::name` here,parameter `this` of condtemp::X::name,invalid access occurs here] codetoanalyze/cpp/pulse/conditionals.cpp, add_test3_latent, 3, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `x` of add_test3_latent,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of add_test3_latent,invalid access occurs here] codetoanalyze/cpp/pulse/conditionals.cpp, add_test5_latent, 5, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,parameter `x` of add_test5_latent,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of add_test5_latent,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_const3_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,parameter `__r` of std::shared_ptr::shared_ptr,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_const4_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_volatile3_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,parameter `__r` of std::shared_ptr::shared_ptr,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_volatile4_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `a` of deduplication::SomeTemplatedClass::lifetime_error_bad,when calling `deduplication::SomeTemplatedClass::templated_wrapper_delete_ok` here,parameter `a` of deduplication::SomeTemplatedClass::templated_wrapper_delete_ok,was invalidated by `delete`,use-after-lifetime part of the trace starts here,parameter `a` of deduplication::SomeTemplatedClass::lifetime_error_bad,when calling `deduplication::SomeTemplatedClass::templated_wrapper_access_ok` here,parameter `a` of deduplication::SomeTemplatedClass::templated_wrapper_access_ok,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `a` of deduplication::SomeTemplatedClass::lifetime_error_bad,when calling `deduplication::SomeTemplatedClass::templated_wrapper_delete_ok` here,parameter `a` of deduplication::SomeTemplatedClass::templated_wrapper_delete_ok,was invalidated by `delete`,use-after-lifetime part of the trace starts here,parameter `a` of deduplication::SomeTemplatedClass::lifetime_error_bad,when calling `deduplication::SomeTemplatedClass::templated_wrapper_access_ok` here,parameter `a` of deduplication::SomeTemplatedClass::templated_wrapper_access_ok,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::templated_function_bad<_Bool>, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,allocated by call to `new` (modelled),assigned,when calling `deduplication::templated_delete_function<_Bool>` here,parameter `a` of deduplication::templated_delete_function<_Bool>,was invalidated by `delete`,use-after-lifetime part of the trace starts here,allocated by call to `new` (modelled),assigned,when calling `deduplication::templated_access_function<_Bool>` here,parameter `a` of deduplication::templated_access_function<_Bool>,invalid access occurs here] @@ -88,6 +92,13 @@ codetoanalyze/cpp/pulse/returns.cpp, returns::return_literal_stack_reference_bad codetoanalyze/cpp/pulse/returns.cpp, returns::return_stack_pointer_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `x` declared here,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference1_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `C++ temporary` declared here,assigned,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference2_bad, 3, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `C++ temporary` declared here,assigned,assigned,returned here] +codetoanalyze/cpp/pulse/shared_ptr_constructors.cpp, shared_ptr_constructors::aliasing_member_null_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `shared_ptr_constructors::ERROR_aliasing_construct_from_internal`,in call to `shared_ptr_constructors::internal_null_def`,is the null pointer,assigned,return from call to `shared_ptr_constructors::internal_null_def`,in call to `std::shared_ptr::shared_ptr`,parameter `__p` of std::shared_ptr::shared_ptr,assigned,return from call to `std::shared_ptr::shared_ptr`,return from call to `shared_ptr_constructors::ERROR_aliasing_construct_from_internal`,in call to `std::shared_ptr::operator->`,parameter `this` of std::shared_ptr::operator->,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref2_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator->`,parameter `this` of std::shared_ptr::operator->,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::get`,parameter `this` of std::shared_ptr::get,returned,return from call to `std::shared_ptr::get`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_method_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator->`,parameter `this` of std::shared_ptr::operator->,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::nullptr_ptr_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::shared_ptr_copy_null_deref_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,parameter `__r` of std::shared_ptr::shared_ptr,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,parameter `this` of std::shared_ptr::operator*,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_strong_impossible_npe1_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_strong_impossible_npe2_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_weak_impossible_npe1_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] @@ -157,3 +168,8 @@ codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_end_read_bad, 3, VECTOR_IN codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_next_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_prev_after_emplace_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_prev_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_read_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `vec` of iterator_read_after_emplace_bad,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_after_reset_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_after_swap_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_empty_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::use_count_after_reset_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::use_count_empty_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/cpp/pulse/issues.exp-isl b/infer/tests/codetoanalyze/cpp/pulse/issues.exp-isl index 430c7ab34..c8bf3f231 100644 --- a/infer/tests/codetoanalyze/cpp/pulse/issues.exp-isl +++ b/infer/tests/codetoanalyze/cpp/pulse/issues.exp-isl @@ -35,6 +35,10 @@ codetoanalyze/cpp/pulse/conditionals.cpp, add_test3_latent, 3, NULLPTR_DEREFEREN codetoanalyze/cpp/pulse/conditionals.cpp, add_test3_latent, 3, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,invalid access occurs here] codetoanalyze/cpp/pulse/conditionals.cpp, add_test5_latent, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,source of the null value part of the trace starts here,is the null pointer,null pointer dereference part of the trace starts here,invalid access occurs here] codetoanalyze/cpp/pulse/conditionals.cpp, add_test5_latent, 5, USE_AFTER_FREE, no_bucket, ERROR, [*** LATENT ***,invalidation part of the trace starts here,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_const3_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_const4_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_volatile3_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/const_volatile_type.cpp, test_volatile4_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `deduplication::SomeTemplatedClass::templated_wrapper_delete_ok` here,was invalidated by `delete`,use-after-lifetime part of the trace starts here,when calling `deduplication::SomeTemplatedClass::templated_wrapper_access_ok` here,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::SomeTemplatedClass::lifetime_error_bad, 2, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,when calling `deduplication::SomeTemplatedClass::templated_wrapper_delete_ok` here,was invalidated by `delete`,use-after-lifetime part of the trace starts here,when calling `deduplication::SomeTemplatedClass::templated_wrapper_access_ok` here,invalid access occurs here] codetoanalyze/cpp/pulse/deduplication.cpp, deduplication::templated_function_bad<_Bool>, 3, USE_AFTER_DELETE, no_bucket, ERROR, [invalidation part of the trace starts here,allocated by call to `new` (modelled),assigned,when calling `deduplication::templated_delete_function<_Bool>` here,was invalidated by `delete`,use-after-lifetime part of the trace starts here,allocated by call to `new` (modelled),assigned,when calling `deduplication::templated_access_function<_Bool>` here,invalid access occurs here] @@ -94,6 +98,13 @@ codetoanalyze/cpp/pulse/returns.cpp, returns::return_literal_stack_reference_bad codetoanalyze/cpp/pulse/returns.cpp, returns::return_stack_pointer_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `x` declared here,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference1_bad, 2, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `C++ temporary` declared here,assigned,returned here] codetoanalyze/cpp/pulse/returns.cpp, returns::return_variable_stack_reference2_bad, 3, STACK_VARIABLE_ADDRESS_ESCAPE, no_bucket, ERROR, [variable `C++ temporary` declared here,assigned,assigned,returned here] +codetoanalyze/cpp/pulse/shared_ptr_constructors.cpp, shared_ptr_constructors::aliasing_member_null_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `shared_ptr_constructors::ERROR_aliasing_construct_from_internal`,in call to `shared_ptr_constructors::internal_null_def`,is the null pointer,assigned,return from call to `shared_ptr_constructors::internal_null_def`,in call to `std::shared_ptr::shared_ptr`,assigned,return from call to `std::shared_ptr::shared_ptr`,return from call to `shared_ptr_constructors::ERROR_aliasing_construct_from_internal`,in call to `std::shared_ptr::operator->`,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref2_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator->`,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_field_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::get`,returned,return from call to `std::shared_ptr::get`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::empty_ptr_method_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator->`,returned,return from call to `std::shared_ptr::operator->`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::nullptr_ptr_deref_bad, 2, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] +codetoanalyze/cpp/pulse/shared_ptr_deref.cpp, shared_ptr::shared_ptr_copy_null_deref_bad, 3, NULLPTR_DEREFERENCE, no_bucket, ERROR, [in call to `std::shared_ptr::shared_ptr`,is the null pointer,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::shared_ptr`,assigned,return from call to `std::shared_ptr::shared_ptr`,in call to `std::shared_ptr::operator*`,returned,return from call to `std::shared_ptr::operator*`,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_strong_impossible_npe1_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_strong_impossible_npe2_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] codetoanalyze/cpp/pulse/std_atomics.cpp, atomic_test::FP_compare_exchange_weak_impossible_npe1_ok, 6, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] @@ -164,3 +175,8 @@ codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_end_read_bad, 3, VECTOR_IN codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_next_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_prev_after_emplace_bad, 4, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] codetoanalyze/cpp/pulse/vector_iterator.cpp, iterator_read_after_emplace_bad, 3, VECTOR_INVALIDATION, no_bucket, ERROR, [invalidation part of the trace starts here,was potentially invalidated by `std::vector::emplace()`,use-after-lifetime part of the trace starts here,variable `iter` declared here,in call to `std::vector::begin()` (modelled),invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_after_reset_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_after_swap_bad, 5, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::expired_empty_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::use_count_after_reset_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [*** LATENT ***,is the null pointer,assigned,invalid access occurs here] +codetoanalyze/cpp/pulse/weak_ptr.cpp, weak_ptr_observers::use_count_empty_bad, 4, NULLPTR_DEREFERENCE, no_bucket, ERROR, [is the null pointer,assigned,invalid access occurs here] diff --git a/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_compil.cpp b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_compil.cpp new file mode 100644 index 000000000..e72284dad --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_compil.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +/* Compilation tests */ + +namespace shared_ptr_conv_from_derived { +/* +shared_ptr conversion does not work if inheritance is not public +*/ +class Base {}; +class Derived : public Base {}; +class Q { + protected: + std::shared_ptr m_; + + public: + void setM(std::shared_ptr m) { m_ = std::move(m); } +}; +class P { + std::shared_ptr m_; + Q q_; + void u() { q_.setM(m_); } +}; +} // namespace shared_ptr_conv_from_derived diff --git a/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_constructors.cpp b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_constructors.cpp new file mode 100644 index 000000000..db5acc4e6 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_constructors.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +namespace shared_ptr_constructors { + +struct Base { + int* f1; +}; + +struct Derived : public Base { + int* f2; +}; + +std::shared_ptr getFromBase1(Base* b) { return std::shared_ptr(b); } + +std::shared_ptr getFromBase2(Base* b) { + std::shared_ptr result; + result = std::shared_ptr(b); // assignment operator + return result; +} + +std::shared_ptr getFromDerived1(Derived* d) { + return std::shared_ptr(d); +} + +std::shared_ptr ERROR_getFromDerived2(Derived* d) { + std::shared_ptr sd(d); + return std::shared_ptr(sd); +} + +std::shared_ptr ERROR_getFromDerived3(Derived* d) { + std::shared_ptr sd(d); + std::shared_ptr result; + result = sd; // assignment operator + return result; +} + +void FN_get_from_base1_nullptr_deref_bad() { + Base b = *(getFromBase1(nullptr)); +} + +void FN_get_from_base2_nullptr_deref_bad() { + Base b = *(getFromBase2(nullptr)); +} + +void FN_get_from_derived1_nullptr_deref_bad() { + Base b = *(getFromDerived1(nullptr)); +} + +void FN_get_from_derived2_nullptr_deref_bad() { + Base b = *(ERROR_getFromDerived2(nullptr)); +} + +void FN_get_from_derived3_nullptr_deref_bad() { + Base b = *(ERROR_getFromDerived3(nullptr)); +} + +void FN_get_from_base1_null_f1_deref_bad() { + Base b; + int v; + b.f1 = &v; + std::shared_ptr p = getFromBase1(&b); + b.f1 = nullptr; + int r = *(p->f1); +} + +void FN_get_from_base2_null_f1_deref_bad() { + Base b; + int v; + b.f1 = &v; + std::shared_ptr p = getFromBase2(&b); + b.f1 = nullptr; + int r = *(p->f1); +} + +void FN_get_from_derived1_null_f1_deref_bad() { + Derived b; + int v; + b.f1 = &v; + std::shared_ptr p = getFromDerived1(&b); + b.f1 = nullptr; + int r = *(p->f1); +} + +void FN_get_from_derived2_null_f1_deref_bad() { + Derived b; + int v; + b.f1 = &v; + std::shared_ptr p = ERROR_getFromDerived2(&b); + b.f1 = nullptr; + int r = *(p->f1); +} + +void FN_get_from_derived3_null_f1_deref_bad() { + Derived b; + int v; + b.f1 = &v; + std::shared_ptr p = ERROR_getFromDerived3(&b); + b.f1 = nullptr; + int r = *(p->f1); +} + +struct A { + void baz(); +}; +struct B { + A* a; +}; + +std::shared_ptr external_def(); +std::shared_ptr internal_null_def() { + // TODO: do the same test for std::make_shared + // We can't use std::make_shared here because it will cause a memory leak to + // be reported instead. In the future we probably need to use something like + // __set_wont_leak_attribute() to suppress the leak report. + auto r = external_def(); + r->a = nullptr; + return r; +} + +std::shared_ptr ERROR_aliasing_construct_from_external() { + auto p = external_def(); + if (!p) + throw std::logic_error("Suppress NULL"); + return {p, p->a}; +} +std::shared_ptr ERROR_aliasing_construct_from_internal() { + auto p = internal_null_def(); + if (!p) + throw std::logic_error("Suppress NULL"); + return {p, p->a}; +} + +void aliasing_member_not_null_ok() { + auto q = ERROR_aliasing_construct_from_external(); + // q is unknown here so we should not report null deref + // Also we should not report dangling pointer because q is still alive + q->baz(); +} +void aliasing_member_null_bad() { + auto q = ERROR_aliasing_construct_from_internal(); + // q is known here so we should report null deref + // Also we should not report dangling pointer because q is still alive + q->baz(); +} +} // namespace shared_ptr_constructors diff --git a/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_deref.cpp b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_deref.cpp new file mode 100644 index 000000000..2225e1c89 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/shared_ptr_deref.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace shared_ptr { + +struct X { + int field; + int get() { return field; } + void set(int value) { field = value; } +}; + +int empty_ptr_access() { + std::shared_ptr x; + int* p = x.get(); // no dereference + if (p) { + return 1; + } + return 0; +} + +int empty_ptr_deref_bad() { + std::shared_ptr x; + return *x; +} + +int nullptr_ptr_deref_bad() { + std::shared_ptr x(nullptr); + return *x; +} + +int empty_ptr_field_deref_bad() { + std::shared_ptr x; + return x.get()->field; +} + +int empty_ptr_field_deref2_bad() { + std::shared_ptr x; + return x->field; +} + +int empty_ptr_method_deref_bad() { + std::shared_ptr x; + return x->get(); +} + +int FN_reset_ptr_null_deref_bad() { + std::shared_ptr x(new int); + x.reset(); + return *x; +} + +int FN_reset_ptr_null_deref2_bad() { + std::shared_ptr x(new int); + x.reset(new int); + x.reset(); + return *x; +} + +int reset_ptr_deref_ok() { + std::shared_ptr x; + x.reset(new int); + return *x; +} + +int reset_ptr_deref2_ok() { + std::shared_ptr x; + x.reset(); + x.reset(new int); + return *x; +} + +int shared_ptr_copy_null_deref_bad() { + std::shared_ptr p1; + std::shared_ptr p2 = p1; + return *p2; +} + +int FN_shared_ptr_assign_null_deref_bad() { + std::shared_ptr p1(new int); + std::shared_ptr p2; + p1 = p2; + return *p1; +} + +// FP is a memory leak +int FP_shared_ptr_copy_deref_ok() { + std::shared_ptr p1(new int); + std::shared_ptr p2 = p1; + return *p2; +} + +// FP is a memory leak +int FP_shared_ptr_assign_deref_ok() { + std::shared_ptr p1(new int); + std::shared_ptr p2; + p2 = p1; + p1.reset(); + return *p2; +} + +int FN_shared_ptr_move_null_deref_bad() { + std::shared_ptr p1(new int); + std::shared_ptr p2 = std::move(p1); + return *p1; +} + +int ERROR_shared_ptr_check_null_ok() { + std::shared_ptr p; + if (p == nullptr) + return 1; + return *p; +} + +int shared_ptr_check_notnull_ok() { + std::shared_ptr p; + if (p != nullptr) + return *p; + return 1; +} + +int shared_ptr_check_null2_ok(std::shared_ptr p) { + if (p == nullptr) + return 1; + return *p; +} +} // namespace shared_ptr diff --git a/infer/tests/codetoanalyze/cpp/pulse/unique_ptr_deref.cpp b/infer/tests/codetoanalyze/cpp/pulse/unique_ptr_deref.cpp new file mode 100644 index 000000000..98d8de3b2 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/unique_ptr_deref.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace unique_ptr { + +struct X { + int field; + int get() { return field; } + void set(int value) { field = value; } +}; + +int empty_ptr_access() { + std::unique_ptr x; + int* p = x.get(); // no dereference + if (p) { + return 1; + } + return 0; +} + +int FN_empty_ptr_deref_bad() { + std::unique_ptr x; + return *x; +} + +int FN_empty_array_ptr_deref_bad() { + std::unique_ptr x; + return x[0]; +} + +int FN_nullptr_ptr_deref_bad() { + std::unique_ptr x(nullptr); + return *x; +} + +int FN_nullptr_array_ptr_deref_bad() { + std::unique_ptr x(nullptr); + return x[2]; +} + +int FN_empty_ptr_field_deref_bad() { + std::unique_ptr x; + return x.get()->field; +} + +int FN_empty_ptr_field_deref2_bad() { + std::unique_ptr x; + return x->field; +} + +int FN_empty_ptr_method_deref_bad() { + std::unique_ptr x; + return x->get(); +} + +// FP is memory leak +int FN_FP_reset_ptr_null_deref_bad() { + std::unique_ptr x(new int); + x.reset(); + return *x; +} + +int FN_FP_reset_ptr_null_deref2_bad() { + std::unique_ptr x(new int); + x.reset(new int); + x.reset(); + return *x; +} + +int FP_reset_ptr_deref_ok() { + std::unique_ptr x; + x.reset(new int); + return *x; +} + +int FP_reset_ptr_deref2_ok() { + std::unique_ptr x; + x.reset(); + x.reset(new int); + return *x; +} + +int FN_unique_ptr_copy_null_deref_bad() { + std::unique_ptr p1; + std::unique_ptr p2 = std::move(p1); + return *p2; +} + +int FN_unique_ptr_assign_null_deref_bad() { + std::unique_ptr p1(new int); + std::unique_ptr p2; + p1 = std::move(p2); + return *p1; +} + +int FP_unique_ptr_move_deref_ok() { + std::unique_ptr p1(new int); + std::unique_ptr p2 = std::move(p1); + return *p2; +} + +int unique_ptr_assign_deref_ok() { + std::unique_ptr p1(new int); + std::unique_ptr p2; + p2 = std::move(p1); + p1.reset(); + return *p2; +} + +int FN_unique_ptr_move_null_deref_bad() { + std::unique_ptr p1(new int); + std::unique_ptr p2 = std::move(p1); + return *p1; +} + +} // namespace unique_ptr + +namespace unique_ptr_with_deleter { + +/* This is just a compilation test */ + +template +class Pointer { + public: + /* No constructor with only one T* argument */ + /* implicit */ Pointer(std::nullptr_t = nullptr) noexcept {} + Pointer(T* ptr, int n) noexcept {} + + friend bool operator==(Pointer a, Pointer b) noexcept { return true; } + friend bool operator!=(Pointer a, Pointer b) noexcept { return true; } + explicit operator bool() const noexcept { return true; } + T* operator->() const noexcept { return get(); } + T& operator*() const noexcept { return *get(); } + T* get() const noexcept { return nullptr; } +}; + +template +struct Deleter { + using pointer = Pointer; + + void operator()(pointer ptr) const {} +}; + +template +using my_unique_ptr = std::unique_ptr>; + +bool instantiate() { + my_unique_ptr p; + my_unique_ptr q; + return p != nullptr && q != nullptr; +} +} // namespace unique_ptr_with_deleter diff --git a/infer/tests/codetoanalyze/cpp/pulse/weak_ptr.cpp b/infer/tests/codetoanalyze/cpp/pulse/weak_ptr.cpp new file mode 100644 index 000000000..52cbe0d51 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/weak_ptr.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +namespace weak_ptr_constructors { + +struct Base { + int* f1; + Base(int* f1 = nullptr) : f1(f1) {} +}; + +struct Derived : public Base { + int* f2; + Derived(int* f1 = nullptr) : Base(f1) {} +}; + +std::weak_ptr empty() { return std::weak_ptr(); } + +std::weak_ptr fromWeakBaseConstr(std::weak_ptr b) { + return std::weak_ptr(b); +} + +std::weak_ptr fromWeakBaseAssign(std::weak_ptr b) { + std::weak_ptr result; + result = b; + return result; +} + +std::weak_ptr fromWeakDerivedConstr(std::weak_ptr d) { + return std::weak_ptr(d); +} + +std::weak_ptr fromWeakDerivedAssign(std::weak_ptr d) { + std::weak_ptr result; + result = d; + return result; +} + +std::weak_ptr fromSharedBaseConstr(std::shared_ptr b) { + return std::weak_ptr(b); +} + +std::weak_ptr fromSharedBaseAssign(std::shared_ptr b) { + std::weak_ptr result; + result = b; + return result; +} + +std::weak_ptr fromSharedDerivedConstr(std::shared_ptr d) { + return std::weak_ptr(d); +} + +std::weak_ptr fromSharedDerivedConstr2(std::shared_ptr d) { + std::weak_ptr sd(d); + return std::weak_ptr(sd); +} + +std::weak_ptr fromSharedDerivedAssign(std::shared_ptr d) { + std::weak_ptr sd(d); + std::weak_ptr result; + result = sd; + return result; +} +} // namespace weak_ptr_constructors + +namespace weak_ptr_derefs { +using namespace weak_ptr_constructors; + +int safeGetFromEmpty_good() { + auto w = empty(); + auto s = w.lock(); + while (!s) + ; + return *s->f1; // never reached +} + +std::shared_ptr safeGet(std::weak_ptr p) { + auto s = p.lock(); + while (!s) + ; + return s; +} + +int FN_safeGetFromWeakBaseConstr_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromWeakBaseConstr(std::weak_ptr(b))); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromWeakBaseAssign_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromWeakBaseAssign(std::weak_ptr(b))); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromWeakDerivedConstr_bad(int v) { + auto d = std::make_shared(&v); + auto s = safeGet(fromWeakDerivedConstr(std::weak_ptr(d))); + d->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromWeakDerivedAssign_bad(int v) { + auto d = std::make_shared(&v); + auto s = safeGet(fromWeakDerivedAssign(std::weak_ptr(d))); + d->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromSharedBaseConstr_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromSharedBaseConstr(b)); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromSharedBaseAssign_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromSharedBaseAssign(b)); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromSharedDerivedConstr_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromSharedDerivedConstr(b)); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromSharedDerivedConstr2_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromSharedDerivedConstr2(b)); + b->f1 = nullptr; + return *s->f1; +} + +int FN_safeGetFromSharedDerivedAssign_bad(int v) { + auto b = std::make_shared(&v); + auto s = safeGet(fromSharedDerivedAssign(b)); + b->f1 = nullptr; + return *s->f1; +} +} // namespace weak_ptr_derefs + +namespace weak_ptr_modifiers { + +void reset(std::weak_ptr& p) { p.reset(); } + +void swap(std::weak_ptr& p) { + std::weak_ptr q; + q.swap(p); +} +} // namespace weak_ptr_modifiers + +namespace weak_ptr_observers { +using namespace weak_ptr_constructors; + +long use_count(std::weak_ptr& p) { return p.use_count(); } + +void use_count_empty_bad() { + std::weak_ptr p; + if (p.use_count() == 0) { + int* x = nullptr; + *x = 42; + } +} + +void use_count_after_reset_bad(std::weak_ptr& p) { + p.reset(); + if (p.use_count() == 0) { + int* x = nullptr; + *x = 42; + } +} + +bool expired(std::weak_ptr& p) { return p.expired(); } + +void expired_empty_bad() { + std::weak_ptr p; + if (p.expired()) { + int* x = nullptr; + *x = 42; + } +} + +void expired_after_reset_bad(std::weak_ptr& p) { + p.reset(); + if (p.expired()) { + int* x = nullptr; + *x = 42; + } +} + +void expired_after_swap_bad(std::weak_ptr& p) { + std::weak_ptr q; + q.swap(p); + if (p.expired()) { + int* x = nullptr; + *x = 42; + } +} + +std::shared_ptr lock(std::weak_ptr& p) { return p.lock(); } + +void FN_empty_weak_lock_returns_null_bad() { + std::weak_ptr p; + auto s = p.lock(); + int _ = *s.get(); +} + +void FN_expired_means_null_bad(std::weak_ptr& p) { + if (p.expired()) { + auto s = p.lock(); + int _ = *s.get(); + } +} + +void FN_lock_can_be_null_bad(std::weak_ptr& p) { + auto s = p.lock(); + int _ = *s.get(); +} + +int safe_deref_ok(std::weak_ptr& p) { + if (auto s = p.lock()) { + return *s.get(); + } + return 0; +} + +std::shared_ptr shared_still_in_scope_good_FP() { + /* It's not a big issue to FP in this case. + Code should not be written like that anyway. */ + auto s = std::make_shared(); + auto p = std::weak_ptr(s); + auto s2 = p.lock(); + auto _ = *s2.get(); + return s; +} + +bool owner_before(std::weak_ptr& p, std::weak_ptr& q) { + return p.owner_before(q); +} + +bool owner_before(std::weak_ptr& p, std::shared_ptr& q) { + return p.owner_before(q); +} +} // namespace weak_ptr_observers diff --git a/infer/tests/codetoanalyze/cpp/pulse/weak_ptr_compil.cpp b/infer/tests/codetoanalyze/cpp/pulse/weak_ptr_compil.cpp new file mode 100644 index 000000000..7c3fab838 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/pulse/weak_ptr_compil.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include +#include +#include +#include + +/* Compilation tests */ + +namespace weak_ptr_lock_repro_small { +template +std::shared_ptr joinT(std::shared_ptr x) { + return x; +}; + +// cannot star +void ERROR_foo(std::weak_ptr p) { + auto self = p.lock(); + std::shared_ptr x = joinT(self); +} +} // namespace weak_ptr_lock_repro_small + +namespace weak_ptr_lock_repro_large { + +class S { + public: + template + std::shared_ptr joinT(std::shared_ptr s); +}; + +class DCC { + public: + const std::shared_ptr& s(); +}; + +class DC {}; + +class CDM { + public: + std::shared_ptr gdc(std::function); +}; + +class RDC : DC { + public: + static std::shared_ptr create(std::function cf); + + private: + const std::shared_ptr cdm; + mutable std::function()> dcf; +}; + +std::shared_ptr RDC::create(std::function cf) { + auto dc = std::make_shared(); + dc->dcf = [cf = std::move(cf), + weakSelf = + std::weak_ptr(dc)]() mutable -> std::shared_ptr { + if (auto self = weakSelf.lock()) { + return self->cdm->gdc([&]() mutable { + auto c = cf(); + c.s()->joinT(self); + return c; + }); + } + return nullptr; + }; + return dc; +} +} // namespace weak_ptr_lock_repro_large + +namespace weak_ptr_owner_less { +class K {}; +class V {}; +class C { + using S = std::set, std::owner_less>>; + std:: + map, std::weak_ptr, std::owner_less>> + m; + S s; +#ifdef INFER_USE_LIBCPP + /* requires Clang headers */ + std::unordered_map u; +#endif +}; +} // namespace weak_ptr_owner_less