Summary:public Create initial model of C++ std::shared_ptr. This means that infer will replace implementation of shared_ptr and the resulting binary will change. Make sure no one will run it by crashing any binary that includes that code. Reviewed By: jvillard Differential Revision: D2999948 fb-gh-sync-id: 5753559 shipit-source-id: 5753559master
parent
b2969820a4
commit
eb76a441f9
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
// this file exists in gcc headers and we need to capture those includes
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <bits/shared_ptr.h>
|
||||
#include <infer_model/end_name_override.inc>
|
||||
|
||||
#include <infer_model/shared_ptr.h>
|
@ -0,0 +1,3 @@
|
||||
#define make_shared std__make_shared
|
||||
#define shared_ptr std__shared_ptr
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <infer_model/portability.h>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#define static_assert(...)
|
||||
|
||||
namespace infer_model {
|
||||
// code compiled with infer headers is not supposed to be executed
|
||||
struct AbortWhenRun {
|
||||
AbortWhenRun() {
|
||||
fprintf(stderr,
|
||||
"!!! This program must not be run !!!\n"
|
||||
"This code was compiled to be analyzed by Infer.\n"
|
||||
"To run this program, recompile it without Infer.\n");
|
||||
std::abort();
|
||||
}
|
||||
};
|
||||
|
||||
static AbortWhenRun a{};
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
#undef make_shared
|
||||
#undef shared_ptr
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// TODO set it in configure script instead
|
||||
// This is hacky attempt to follow what folly does
|
||||
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/configure.ac#L232
|
||||
#if !defined(INFER_USE_LIBCPP) && defined(__APPLE__)
|
||||
#define INFER_USE_LIBCPP 1
|
||||
#elif defined(FOLLY_USE_LIBCPP)
|
||||
#define INFER_USE_LIBCPP 1
|
||||
#endif
|
||||
|
||||
// Follow what folly does - gnu libstdc++ implementation is different from
|
||||
// llvm's libc++. This way folly can forward declare decls from std library
|
||||
// even when they are infer models
|
||||
// https://github.com/facebook/folly/blob/b1eb6819f3ffe6b645f39d505ca8ace3116b7873/folly/Portability.h#L253-L255
|
||||
#if INFER_USE_LIBCPP
|
||||
#include <__config>
|
||||
#define INFER_NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
#define INFER_NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD
|
||||
#else
|
||||
#define INFER_NAMESPACE_STD_BEGIN namespace std {
|
||||
#define INFER_NAMESPACE_STD_END }
|
||||
#endif
|
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// ASSERT that __cplusplus >= 201103L
|
||||
|
||||
#include <infer_model/common.h>
|
||||
|
||||
INFER_NAMESPACE_STD_BEGIN
|
||||
|
||||
// use inheritance to avoid compilation errors when using
|
||||
// methods / non-member functions that are not modeled
|
||||
// WARNING: sizeof(shared_ptr) = 24, not 16 - this may
|
||||
// lead to compilation errors
|
||||
template <class T>
|
||||
class shared_ptr : public std__shared_ptr<T> {
|
||||
|
||||
public:
|
||||
// Conversion constructors to allow implicit conversions.
|
||||
// it's here purely to avoid compilation errors
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(const std__shared_ptr<Y>& r) {}
|
||||
|
||||
template <class Y>
|
||||
shared_ptr(const std__shared_ptr<Y>& r, T* p) noexcept {}
|
||||
|
||||
T* data;
|
||||
|
||||
// constructors:
|
||||
constexpr shared_ptr() noexcept : data(nullptr) {}
|
||||
|
||||
shared_ptr(nullptr_t) : shared_ptr() {}
|
||||
|
||||
// Extra template argument is used to create constructors/assignment overloads
|
||||
// for Y types where it's possible to convert Y* to T*.
|
||||
// typename = typename enable_if<is_convertible<Y*, T*>::value>::type
|
||||
// thanks to that, clang will not create some functions that would cause
|
||||
// compilation errors. More info:
|
||||
// http://en.cppreference.com/w/cpp/language/sfinae
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
explicit shared_ptr(Y* p) {
|
||||
data = p;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(Y* p, D d) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
class A,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(Y* p, D d, A a) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class D>
|
||||
shared_ptr(nullptr_t p, D d) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class D, class A>
|
||||
shared_ptr(nullptr_t p, D d, A a) : shared_ptr<T>(p) {}
|
||||
|
||||
template <class Y>
|
||||
shared_ptr(const shared_ptr<Y>& r, T* p) noexcept : data(nullptr) { /* TODO */
|
||||
}
|
||||
|
||||
shared_ptr(const shared_ptr& r) noexcept
|
||||
: shared_ptr<T>(r.data) { /* TODO - increase refcount*/
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(const shared_ptr<Y>& r) noexcept
|
||||
: shared_ptr<T>(r.data) { /* TODO - increase refcount*/
|
||||
}
|
||||
|
||||
shared_ptr(shared_ptr&& r) noexcept : shared_ptr<T>(r.data) {
|
||||
r.data = nullptr;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(shared_ptr<Y>&& r) noexcept : shared_ptr<T>(r.data) {
|
||||
r.data = nullptr;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
explicit shared_ptr(const weak_ptr<Y>& r) {}
|
||||
|
||||
/* Because of implementation differences between libc++ and stdlibc++, don't
|
||||
* define this constructor (it will be defined elsewhere in case of
|
||||
* stdlibc++). Because it may be defined elsewhere, don't check whether Y*
|
||||
* converts to T* - otherwise there might be compilation error (out-of-line
|
||||
* definition).
|
||||
* No definition here might cause compilation problems if project is
|
||||
* using auto_ptrs with libc++ */
|
||||
template <class Y>
|
||||
shared_ptr(auto_ptr<Y>&& r); // {}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr(unique_ptr<Y, D>&& r) : shared_ptr<T>(r.release()) {}
|
||||
|
||||
// destructor:
|
||||
~shared_ptr() { reset((T*)nullptr); }
|
||||
|
||||
// assignment:
|
||||
shared_ptr& operator=(const shared_ptr& r) noexcept {
|
||||
// shared_ptr<T>(r).swap(*this);
|
||||
data = r.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(const shared_ptr<Y>& r) noexcept {
|
||||
// shared_ptr<T>(r).swap(*this);
|
||||
data = r.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
shared_ptr& operator=(shared_ptr&& r) noexcept {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
data = r.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(shared_ptr<Y>&& r) {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
data = r.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(auto_ptr<Y>&& r) { /* ?? */
|
||||
}
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
shared_ptr& operator=(unique_ptr<Y, D>&& r) {
|
||||
// shared_ptr<T>(std::move(r)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// modifiers:
|
||||
void swap(shared_ptr& r) noexcept {
|
||||
T* tmp = r.data;
|
||||
r.data = data;
|
||||
data = tmp;
|
||||
}
|
||||
|
||||
void reset() noexcept { reset((T*)nullptr); }
|
||||
|
||||
template <class Y,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p) {
|
||||
/*
|
||||
if (unique()) {
|
||||
delete data;
|
||||
}
|
||||
*/
|
||||
data = p;
|
||||
// TODO adjust refcounts
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p, D d) {
|
||||
reset(p);
|
||||
}
|
||||
|
||||
template <class Y,
|
||||
class D,
|
||||
class A,
|
||||
typename = typename enable_if<is_convertible<Y*, T*>::value>::type>
|
||||
void reset(Y* p, D d, A a) {
|
||||
reset(p);
|
||||
}
|
||||
|
||||
// observers:
|
||||
T* get() const noexcept { return data; }
|
||||
typename add_lvalue_reference<T>::type operator*() const noexcept {
|
||||
return *data;
|
||||
}
|
||||
T* operator->() const noexcept { return data; }
|
||||
long use_count() const noexcept { return 2; /* FIXME */ }
|
||||
bool unique() const noexcept { return use_count() == 1; /* FIXME */ }
|
||||
explicit operator bool() const noexcept { return (bool)data; }
|
||||
template <class U>
|
||||
bool owner_before(shared_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det*/
|
||||
}
|
||||
template <class U>
|
||||
bool owner_before(weak_ptr<U> const& b) const {
|
||||
return true; /* FIXME - use non-det */
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct hash<shared_ptr<T>> : public hash<std__shared_ptr<T>> {};
|
||||
|
||||
// shared_ptr casts - call original functions but change return type to
|
||||
// std::shared_ptr
|
||||
template <class T, class U>
|
||||
shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return static_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
template <class T, class U>
|
||||
shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return dynamic_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
template <class T, class U>
|
||||
shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r) noexcept {
|
||||
return const_pointer_cast<T, U>((const std__shared_ptr<U>&)r);
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
shared_ptr<T> make_shared(Args&&... args) {
|
||||
return shared_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
INFER_NAMESPACE_STD_END
|
@ -0,0 +1,13 @@
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
|
||||
#include <infer_model/begin_name_override.inc>
|
||||
#include_next <memory>
|
||||
#include <infer_model/end_name_override.inc>
|
||||
|
||||
#include<infer_model/shared_ptr.h>
|
||||
|
||||
#else // __cplusplus < 201103L
|
||||
// don't model memory for pre-C++11 code
|
||||
#include_next <memory>
|
||||
#endif
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
struct X {
|
||||
int field;
|
||||
int* getPtr() { return &field; }
|
||||
int* getNull() { return nullptr; }
|
||||
};
|
||||
|
||||
struct SmartPtr {
|
||||
SmartPtr() : data(nullptr) {}
|
||||
X* data;
|
||||
X* get() { return data; }
|
||||
};
|
||||
|
||||
void smart_ptr_null_field_deref() {
|
||||
SmartPtr p;
|
||||
int f = p.get()->field;
|
||||
}
|
||||
|
||||
void smart_ptr_null_method_deref() {
|
||||
SmartPtr p;
|
||||
int* f = p.get()->getPtr();
|
||||
}
|
||||
|
||||
void smart_ptr_null_method_deref2() {
|
||||
SmartPtr p;
|
||||
int* f = p.get()->getNull();
|
||||
}
|
||||
|
||||
void smart_ptr_ok_field_deref() {
|
||||
SmartPtr p;
|
||||
X x;
|
||||
p.data = &x;
|
||||
int f = p.get()->field;
|
||||
}
|
||||
|
||||
void smart_ptr_ok_method_deref() {
|
||||
SmartPtr p;
|
||||
X x;
|
||||
p.data = &x;
|
||||
int* f = p.get()->getNull();
|
||||
int* g = f;
|
||||
}
|
||||
|
||||
void smart_ptr_result_method_null_deref() {
|
||||
SmartPtr p;
|
||||
X x;
|
||||
p.data = &x;
|
||||
int f = *(p.get()->getNull());
|
||||
}
|
||||
|
||||
void smart_ptr_result_method_ok_deref() {
|
||||
SmartPtr p;
|
||||
X x;
|
||||
p.data = &x;
|
||||
int f = *(p.get()->getPtr());
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct Base {
|
||||
int* f1;
|
||||
};
|
||||
|
||||
struct Derived : public Base {
|
||||
int* f2;
|
||||
};
|
||||
|
||||
std::shared_ptr<Base> getFromBase1(Base* b) { return std::shared_ptr<Base>(b); }
|
||||
|
||||
std::shared_ptr<Base> getFromBase2(Base* b) {
|
||||
std::shared_ptr<Base> result;
|
||||
result = std::shared_ptr<Base>(b); // assignment operator
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<Base> getFromDerived1(Derived* d) {
|
||||
return std::shared_ptr<Base>(d);
|
||||
}
|
||||
|
||||
std::shared_ptr<Base> getFromDerived2(Derived* d) {
|
||||
std::shared_ptr<Derived> sd(d);
|
||||
return std::shared_ptr<Base>(sd);
|
||||
}
|
||||
|
||||
std::shared_ptr<Base> getFromDerived3(Derived* d) {
|
||||
std::shared_ptr<Derived> sd(d);
|
||||
std::shared_ptr<Base> result;
|
||||
result = sd; // assignment operator
|
||||
return result;
|
||||
}
|
||||
|
||||
void get_from_base1_nullptr_deref() { Base b = *(getFromBase1(nullptr)); }
|
||||
|
||||
void get_from_base2_nullptr_deref() { Base b = *(getFromBase2(nullptr)); }
|
||||
|
||||
void get_from_derived1_nullptr_deref() { Base b = *(getFromDerived1(nullptr)); }
|
||||
|
||||
void get_from_derived2_nullptr_deref() { Base b = *(getFromDerived2(nullptr)); }
|
||||
|
||||
void get_from_derived3_nullptr_deref() { Base b = *(getFromDerived3(nullptr)); }
|
||||
|
||||
void get_from_base1_null_f1_deref() {
|
||||
Base b;
|
||||
int v;
|
||||
b.f1 = &v;
|
||||
std::shared_ptr<Base> p = getFromBase1(&b);
|
||||
b.f1 = nullptr;
|
||||
int r = *(p->f1);
|
||||
}
|
||||
|
||||
void get_from_base2_null_f1_deref() {
|
||||
Base b;
|
||||
int v;
|
||||
b.f1 = &v;
|
||||
std::shared_ptr<Base> p = getFromBase2(&b);
|
||||
b.f1 = nullptr;
|
||||
int r = *(p->f1);
|
||||
}
|
||||
|
||||
void get_from_derived1_null_f1_deref() {
|
||||
Derived b;
|
||||
int v;
|
||||
b.f1 = &v;
|
||||
std::shared_ptr<Base> p = getFromDerived1(&b);
|
||||
b.f1 = nullptr;
|
||||
int r = *(p->f1);
|
||||
}
|
||||
|
||||
void get_from_derived2_null_f1_deref() {
|
||||
Derived b;
|
||||
int v;
|
||||
b.f1 = &v;
|
||||
std::shared_ptr<Base> p = getFromDerived2(&b);
|
||||
b.f1 = nullptr;
|
||||
int r = *(p->f1);
|
||||
}
|
||||
|
||||
void get_from_derived3_null_f1_deref() {
|
||||
Derived b;
|
||||
int v;
|
||||
b.f1 = &v;
|
||||
std::shared_ptr<Base> p = getFromDerived3(&b);
|
||||
b.f1 = nullptr;
|
||||
int r = *(p->f1);
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
struct X {
|
||||
int field;
|
||||
int get() { return field; }
|
||||
void set(int value) { field = value; }
|
||||
};
|
||||
|
||||
int empty_ptr_access() {
|
||||
std::shared_ptr<int> x;
|
||||
int* p = x.get(); // no dereference
|
||||
if (p) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int empty_ptr_deref() {
|
||||
std::shared_ptr<int> x;
|
||||
return *x;
|
||||
}
|
||||
|
||||
int nullptr_ptr_deref() {
|
||||
std::shared_ptr<int> x(nullptr);
|
||||
return *x;
|
||||
}
|
||||
|
||||
int empty_ptr_field_deref() {
|
||||
std::shared_ptr<X> x;
|
||||
return x.get()->field;
|
||||
}
|
||||
|
||||
int empty_ptr_field_deref2() {
|
||||
std::shared_ptr<X> x;
|
||||
return x->field;
|
||||
}
|
||||
|
||||
int empty_ptr_method_deref() {
|
||||
std::shared_ptr<X> x;
|
||||
return x->get();
|
||||
}
|
||||
|
||||
int reset_ptr_null_deref() {
|
||||
std::shared_ptr<int> x(new int);
|
||||
x.reset();
|
||||
return *x;
|
||||
}
|
||||
|
||||
int reset_ptr_null_deref2() {
|
||||
std::shared_ptr<int> x(new int);
|
||||
x.reset(new int);
|
||||
x.reset();
|
||||
return *x;
|
||||
}
|
||||
|
||||
int reset_ptr_ok_deref() {
|
||||
std::shared_ptr<int> x;
|
||||
x.reset(new int);
|
||||
return *x;
|
||||
}
|
||||
|
||||
int reset_ptr_ok_deref2() {
|
||||
std::shared_ptr<int> x;
|
||||
x.reset();
|
||||
x.reset(new int);
|
||||
return *x;
|
||||
}
|
||||
|
||||
int shared_ptr_copy_null_deref() {
|
||||
std::shared_ptr<int> p1;
|
||||
std::shared_ptr<int> p2 = p1;
|
||||
return *p2;
|
||||
}
|
||||
|
||||
int shared_ptr_assign_null_deref() {
|
||||
std::shared_ptr<int> p1(new int);
|
||||
std::shared_ptr<int> p2;
|
||||
p1 = p2;
|
||||
return *p1;
|
||||
}
|
||||
|
||||
int shared_ptr_copy_ok_deref() {
|
||||
std::shared_ptr<int> p1(new int);
|
||||
std::shared_ptr<int> p2 = p1;
|
||||
return *p2;
|
||||
}
|
||||
|
||||
int shared_ptr_assign_ok_deref() {
|
||||
std::shared_ptr<int> p1(new int);
|
||||
std::shared_ptr<int> p2;
|
||||
p2 = p1;
|
||||
p1.reset();
|
||||
return *p2;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.cpp;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsExactly.containsExactly;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.DebuggableTemporaryFolder;
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
import utils.InferRunner;
|
||||
|
||||
public class BoxedPtrTest {
|
||||
|
||||
public static final String FILE =
|
||||
"infer/tests/codetoanalyze/cpp/errors/npe/boxed_ptr.cpp";
|
||||
|
||||
private static ImmutableList<String> inferCmd;
|
||||
|
||||
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
|
||||
|
||||
@ClassRule
|
||||
public static DebuggableTemporaryFolder folder =
|
||||
new DebuggableTemporaryFolder();
|
||||
|
||||
@BeforeClass
|
||||
public static void runInfer() throws InterruptedException, IOException {
|
||||
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInferRunsNullDerefFunctionsErrorIsFound()
|
||||
throws InterruptedException, IOException, InferException {
|
||||
String[] procedures = {
|
||||
"smart_ptr_null_field_deref",
|
||||
"smart_ptr_null_method_deref",
|
||||
"smart_ptr_null_method_deref2",
|
||||
"smart_ptr_result_method_null_deref",
|
||||
};
|
||||
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
|
||||
assertThat(
|
||||
"Results should contain divide by 0 error",
|
||||
inferResults,
|
||||
containsExactly(
|
||||
NULL_DEREFERENCE,
|
||||
FILE,
|
||||
procedures
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.cpp;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsExactly.containsExactly;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.DebuggableTemporaryFolder;
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
import utils.InferRunner;
|
||||
|
||||
public class SharedPtrConstructorsTest {
|
||||
|
||||
public static final String FILE =
|
||||
"infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_constructors.cpp";
|
||||
|
||||
private static ImmutableList<String> inferCmd;
|
||||
|
||||
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
|
||||
|
||||
@ClassRule
|
||||
public static DebuggableTemporaryFolder folder =
|
||||
new DebuggableTemporaryFolder();
|
||||
|
||||
@BeforeClass
|
||||
public static void runInfer() throws InterruptedException, IOException {
|
||||
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInferRunsNullDerefFunctionsErrorIsFound()
|
||||
throws InterruptedException, IOException, InferException {
|
||||
String[] procedures = {
|
||||
"get_from_base1_nullptr_deref",
|
||||
"get_from_base2_nullptr_deref",
|
||||
"get_from_derived1_nullptr_deref",
|
||||
"get_from_derived2_nullptr_deref",
|
||||
"get_from_derived3_nullptr_deref",
|
||||
"get_from_base1_null_f1_deref",
|
||||
"get_from_base2_null_f1_deref",
|
||||
"get_from_derived1_null_f1_deref",
|
||||
"get_from_derived2_null_f1_deref",
|
||||
"get_from_derived3_null_f1_deref",
|
||||
};
|
||||
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
|
||||
assertThat(
|
||||
"Results should contain divide by 0 error",
|
||||
inferResults,
|
||||
containsExactly(
|
||||
NULL_DEREFERENCE,
|
||||
FILE,
|
||||
procedures
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2016 - present Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
package endtoend.cpp;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static utils.matchers.ResultContainsExactly.containsExactly;
|
||||
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import utils.DebuggableTemporaryFolder;
|
||||
import utils.InferException;
|
||||
import utils.InferResults;
|
||||
import utils.InferRunner;
|
||||
|
||||
public class SharedPtrDerefTest {
|
||||
|
||||
public static final String FILE =
|
||||
"infer/tests/codetoanalyze/cpp/errors/smart_ptr/shared_ptr_deref.cpp";
|
||||
|
||||
private static ImmutableList<String> inferCmd;
|
||||
|
||||
public static final String NULL_DEREFERENCE = "NULL_DEREFERENCE";
|
||||
|
||||
@ClassRule
|
||||
public static DebuggableTemporaryFolder folder =
|
||||
new DebuggableTemporaryFolder();
|
||||
|
||||
@BeforeClass
|
||||
public static void runInfer() throws InterruptedException, IOException {
|
||||
inferCmd = InferRunner.createCPPInferCommand(folder, FILE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInferRunsNullDerefFunctionsErrorIsFound()
|
||||
throws InterruptedException, IOException, InferException {
|
||||
String[] procedures = {
|
||||
"empty_ptr_deref",
|
||||
"nullptr_ptr_deref",
|
||||
"empty_ptr_field_deref",
|
||||
"empty_ptr_field_deref2",
|
||||
"empty_ptr_method_deref",
|
||||
"reset_ptr_null_deref",
|
||||
"reset_ptr_null_deref2",
|
||||
"shared_ptr_copy_null_deref",
|
||||
"shared_ptr_assign_null_deref",
|
||||
};
|
||||
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
|
||||
assertThat(
|
||||
"Results should contain divide by 0 error",
|
||||
inferResults,
|
||||
containsExactly(
|
||||
NULL_DEREFERENCE,
|
||||
FILE,
|
||||
procedures
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in new issue