From bd90e808590461ded1c177a350be2a174e85f0ca Mon Sep 17 00:00:00 2001 From: Jia Chen Date: Fri, 21 Jul 2017 10:28:13 -0700 Subject: [PATCH] Added model for std::shared_ptr's aliasing constructor Reviewed By: mbouaziz Differential Revision: D5467757 fbshipit-source-id: 2dcdf45 --- .../cpp/include/infer_model/shared_ptr.h | 2 +- .../tests/codetoanalyze/cpp/errors/issues.exp | 1 + .../smart_ptr/shared_ptr_constructors.cpp | 45 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/infer/models/cpp/include/infer_model/shared_ptr.h b/infer/models/cpp/include/infer_model/shared_ptr.h index ca57de4d8..72d2db9c8 100644 --- a/infer/models/cpp/include/infer_model/shared_ptr.h +++ b/infer/models/cpp/include/infer_model/shared_ptr.h @@ -134,7 +134,7 @@ class shared_ptr : public std__shared_ptr { template shared_ptr(const shared_ptr& r, T* p) noexcept { - model_set(__cast_to_infer_ptr(this), nullptr); /* TODO */ + model_set(__cast_to_infer_ptr(this), p); /* TODO */ } shared_ptr(const shared_ptr& r) noexcept { diff --git a/infer/tests/codetoanalyze/cpp/errors/issues.exp b/infer/tests/codetoanalyze/cpp/errors/issues.exp index 4fab4a68d..49f217cac 100644 --- a/infer/tests/codetoanalyze/cpp/errors/issues.exp +++ b/infer/tests/codetoanalyze/cpp/errors/issues.exp @@ -84,6 +84,7 @@ codetoanalyze/cpp/errors/smart_ptr/const_volatile_type.cpp, test_volatile4, 2, N codetoanalyze/cpp/errors/smart_ptr/deref_after_move_example.cpp, deref_after_mode_example::deref_after_move_crash, 4, NULL_DEREFERENCE, [start of procedure deref_after_mode_example::deref_after_move_crash(),start of procedure Person,return from a call to deref_after_mode_example::Person_Person,start of procedure move_age,return from a call to deref_after_mode_example::Person_move_age,start of procedure access_age] codetoanalyze/cpp/errors/smart_ptr/deref_after_move_example.cpp, deref_after_mode_example::deref_after_move_ok, 4, MEMORY_LEAK, [start of procedure deref_after_mode_example::deref_after_move_ok(),start of procedure Person,return from a call to deref_after_mode_example::Person_Person,start of procedure move_age,return from a call to deref_after_mode_example::Person_move_age,return from a call to deref_after_mode_example::deref_after_move_ok] codetoanalyze/cpp/errors/smart_ptr/deref_after_move_example.cpp, deref_after_mode_example::deref_ok, 3, MEMORY_LEAK, [start of procedure deref_after_mode_example::deref_ok(),start of procedure Person,return from a call to deref_after_mode_example::Person_Person,start of procedure access_age,return from a call to deref_after_mode_example::Person_access_age,return from a call to deref_after_mode_example::deref_ok] +codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::aliasing_member_null_bad, 4, NULL_DEREFERENCE, [start of procedure shared_ptr_constructors::aliasing_member_null_bad(),start of procedure shared_ptr_constructors::aliasing_construct_from_internal(),start of procedure shared_ptr_constructors::internal_null_def(),Skipped call: function or method not found,return from a call to shared_ptr_constructors::internal_null_def,Condition is true,Condition is false,return from a call to shared_ptr_constructors::aliasing_construct_from_internal] codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::get_from_base1_null_f1_deref, 6, NULL_DEREFERENCE, [start of procedure shared_ptr_constructors::get_from_base1_null_f1_deref(),start of procedure Base,return from a call to shared_ptr_constructors::Base_Base,start of procedure shared_ptr_constructors::getFromBase1(),return from a call to shared_ptr_constructors::getFromBase1] codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::get_from_base1_nullptr_deref, 0, NULL_DEREFERENCE, [start of procedure shared_ptr_constructors::get_from_base1_nullptr_deref(),start of procedure shared_ptr_constructors::getFromBase1(),return from a call to shared_ptr_constructors::getFromBase1] codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp, shared_ptr_constructors::get_from_base2_null_f1_deref, 6, NULL_DEREFERENCE, [start of procedure shared_ptr_constructors::get_from_base2_null_f1_deref(),start of procedure Base,return from a call to shared_ptr_constructors::Base_Base,start of procedure shared_ptr_constructors::getFromBase2(),return from a call to shared_ptr_constructors::getFromBase2] diff --git a/infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp b/infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp index c173b5712..596f617b8 100644 --- a/infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp +++ b/infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp @@ -8,6 +8,7 @@ */ #include +#include namespace shared_ptr_constructors { @@ -97,4 +98,48 @@ void get_from_derived3_null_f1_deref() { 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 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() { + 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 = 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(); + // q is known here so we should report null deref + // Also we should not report dangling pointer because q is still alive + q->baz(); +} }