zc::member<C> c;
rc = &c;
EXPECT(rc == &c);
- c->DoThing();
+ c.DoThing();
}
EXPECT_UAF(rc->DoThing());
}
}
EXPECT_UAF(ref->DoThing());
EXPECT_UAF(vec_ref->at(1).DoThing());
+
+ {
+ zc::member<X> x("foo bar");
+ ref = x.c();
+ }
+ EXPECT_UAF(ref->DoThing());
}
#define TEST_FUNC(fn) { #fn , Test##fn }
namespace internal {
+enum class OwnershipBehavior {
+ DELETE_POINTER,
+ BORROW_POINTER,
+};
+
template <typename T>
class OwnedPtrDeleter {
public:
- OwnedPtrDeleter() {}
+ OwnedPtrDeleter() : refs_(), behavior_(OwnershipBehavior::DELETE_POINTER) {}
~OwnedPtrDeleter() {}
- OwnedPtrDeleter(OwnedPtrDeleter&& other) : refs_(std::move(other.refs_)) {
+ explicit OwnedPtrDeleter(OwnershipBehavior behavior)
+ : refs_(),
+ behavior_(behavior) {
+ }
+
+ OwnedPtrDeleter(OwnedPtrDeleter&& other)
+ : refs_(std::move(other.refs_)),
+ behavior_(other.behavior_) {
}
void operator=(const OwnedPtrDeleter& o) {
refs_ = o.refs_;
+ behavior_ = o.behavior_;
}
void operator()(T* t) const {
for (auto& ref : refs_) {
ref->MarkDeleted();
}
- delete t;
+ if (behavior_ == OwnershipBehavior::DELETE_POINTER) {
+ delete t;
+ }
}
protected:
private:
std::forward_list<ref<T>*> refs_;
+ OwnershipBehavior behavior_;
};
void RaiseUseAfterFree(const char* error) __attribute__((noreturn));
};
template <typename T>
-class member {
+class member : public T {
public:
- template <typename... Args>
- explicit member(Args&&... args)
- : t_(new T(std::forward<Args>(args)...)) {
- }
+ using T::T;
ref<T> operator&() {
- return t_.get();
- }
-
- T* operator->() {
- return t_.operator->();
- }
-
- const T* operator->() const {
- return t_.operator->();
+ return ptr_.get();
}
private:
- owned<T> t_;
+ owned<T> ptr_ = owned<T>(this,
+ internal::OwnedPtrDeleter<T>(
+ internal::OwnershipBehavior::BORROW_POINTER));
};
#else
using ref = T*;
template <typename T>
-class member : public T {
- public:
- using T::T;
-
- T* operator->() {
- return this;
- }
-
- const T* operator->() const {
- return this;
- }
-};
+using member = T;
#endif