Fix unique_ptr model

Summary:
Our model of unique_ptr and shared_ptr relied on the fact that we could C-style cast a pointer to the internal pointer type used in the smart pointer.
This is wrong when the smart pointer is used with a custom deleter that declares its own pointer type whose is not constructible from just a single pointer.

Reviewed By: dulmarod

Differential Revision: D6496203

fbshipit-source-id: 1305137
master
Mehdi Bouaziz 7 years ago committed by Facebook Github Bot
parent b23eca2bbc
commit 1a117d7e09

@ -77,8 +77,6 @@ class shared_ptr : public std__shared_ptr<T> {
model_set(other, nullptr); model_set(other, nullptr);
} }
static T* model_get(infer_shared_ptr_t self) { return (T*)(*self); }
static void model_swap(infer_shared_ptr_t infer_self, static void model_swap(infer_shared_ptr_t infer_self,
infer_shared_ptr_t infer_other) { infer_shared_ptr_t infer_other) {
const void* t = *infer_self; const void* t = *infer_self;
@ -268,7 +266,7 @@ class shared_ptr : public std__shared_ptr<T> {
explicit operator bool() const noexcept { explicit operator bool() const noexcept {
// for some reason analyzer can't cast to bool correctly, trick with two // for some reason analyzer can't cast to bool correctly, trick with two
// negations creates right specs for this function // negations creates right specs for this function
return !!(bool)(model_get(__cast_to_infer_ptr(this))); return !!(bool)(*__cast_to_infer_ptr(this));
} }
template <class U> template <class U>
bool owner_before(shared_ptr<U> const& b) const { bool owner_before(shared_ptr<U> const& b) const {

@ -81,10 +81,6 @@ struct unique_ptr {
model_set(other, nullptr); model_set(other, nullptr);
} }
static pointer model_get(infer_unique_ptr_t self) noexcept {
return (pointer)(*self);
}
static void model_swap(infer_unique_ptr_t infer_self, static void model_swap(infer_unique_ptr_t infer_self,
infer_unique_ptr_t infer_other) noexcept { infer_unique_ptr_t infer_other) noexcept {
const void* t = *infer_self; const void* t = *infer_self;
@ -179,7 +175,7 @@ struct unique_ptr {
_Dp_reference get_deleter() {} _Dp_reference get_deleter() {}
explicit operator bool() const { explicit operator bool() const {
return !!(bool)(model_get(__cast_to_infer_ptr(this))); return !!(bool)(*__cast_to_infer_ptr(this));
} }
pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG; pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG;
@ -235,10 +231,6 @@ struct unique_ptr<_Tp[], _Dp> {
model_set(other, nullptr); model_set(other, nullptr);
} }
static pointer model_get(infer_unique_ptr_t self) noexcept {
return (pointer)(*self);
}
static void model_swap(infer_unique_ptr_t infer_self, static void model_swap(infer_unique_ptr_t infer_self,
infer_unique_ptr_t infer_other) noexcept { infer_unique_ptr_t infer_other) noexcept {
const void* t = *infer_self; const void* t = *infer_self;
@ -329,7 +321,7 @@ struct unique_ptr<_Tp[], _Dp> {
_Dp_reference get_deleter() {} _Dp_reference get_deleter() {}
explicit operator bool() const { explicit operator bool() const {
return !!(bool)(model_get(__cast_to_infer_ptr(this))); return !!(bool)(*__cast_to_infer_ptr(this));
} }
pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG; pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG;

@ -1,4 +1,5 @@
INFER_MODEL/cpp/include/infer_model/shared_ptr.h, std::make_shared<lol>, 1, MEMORY_LEAK, [start of procedure std::make_shared<lol>(),Skipping lol: function or method not found] INFER_MODEL/cpp/include/infer_model/shared_ptr.h, std::make_shared<lol>, 1, MEMORY_LEAK, [start of procedure std::make_shared<lol>(),Skipping lol: function or method not found]
INFER_MODEL/cpp/include/infer_model/unique_ptr.h, std::operator!=<65d659492edc5cb5>, 1, Abduction_case_not_implemented, [start of procedure std::operator!=<65d659492edc5cb5>()]
codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, crash_fgetc, 4, NULL_DEREFERENCE, [start of procedure crash_fgetc()] codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, crash_fgetc, 4, NULL_DEREFERENCE, [start of procedure crash_fgetc()]
codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, crash_getc, 4, NULL_DEREFERENCE, [start of procedure crash_getc()] codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, crash_getc, 4, NULL_DEREFERENCE, [start of procedure crash_getc()]
codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, malloc_fail_gets_reported, 2, NULL_DEREFERENCE, [start of procedure malloc_fail_gets_reported()] codetoanalyze/cpp/errors/c_tests/c_bugs.cpp, malloc_fail_gets_reported, 2, NULL_DEREFERENCE, [start of procedure malloc_fail_gets_reported()]

@ -119,4 +119,41 @@ int unique_ptr_move_null_deref() {
std::unique_ptr<int> p2 = std::move(p1); std::unique_ptr<int> p2 = std::move(p1);
return *p1; return *p1;
} }
} // namespace unique_ptr
namespace unique_ptr_with_deleter {
/* This is just a compilation test */
template <class T>
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 <class T>
struct Deleter {
using pointer = Pointer<T>;
void operator()(pointer ptr) const {}
};
template <class T>
using my_unique_ptr = std::unique_ptr<T, Deleter<T>>;
bool instantiate() {
my_unique_ptr<int> p;
my_unique_ptr<int[]> q;
return p != nullptr && q != nullptr;
}
} }

Loading…
Cancel
Save