From b05b787894c21df3a94584e2a048ce0fe9008050 Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Mon, 10 Oct 2016 14:56:42 -0400 Subject: [PATCH] Add member for non-pointer member varibables and stack locals. --- Makefile | 4 ++-- README.md | 5 ++++- test.cc | 38 +++++++++++++++++++++++++++++++------- test_helpers.cc | 34 ++++++++++++++++++++++++++++++++++ test_helpers.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ zcpointer.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 164 insertions(+), 10 deletions(-) create mode 100644 test_helpers.cc create mode 100644 test_helpers.h diff --git a/Makefile b/Makefile index 2245bf2..5b8d2af 100644 --- a/Makefile +++ b/Makefile @@ -5,9 +5,9 @@ ifeq ($(OPTIMIZED),1) CXXFLAGS += -O2 endif -FILES := test.cc zcpointer.cc +FILES := test.cc test_helpers.cc zcpointer.cc -DEPS := $(FILES) zcpointer.h Makefile +DEPS := $(FILES) zcpointer.h test_helpers.h Makefile all: test-zc test-tr diff --git a/README.md b/README.md index 571a611..68cc5e2 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,15 @@ The zcpointer library is a specialization of references. The goal is to allow C++ developers to write programs without _ever_ having a pointer that is not automatically managed by a smart scoper. -The library provides two types to do this: +The library provides three types to do this: - `zc::owned` provides an identical interface to `std::unique_ptr`, but which can track outstanding weak references. - `zc::ref` is the return value of `zc::owned::get()`. It stands for a `T*` but is used to ensure use-after-free does not occur. +- `zc::member` is used to wrap member or local variables that should be constructed in-place, but + which may have pointers-to vended out to other objects. This overloads `zc::member::operator&` + to return a `zc::ref` when taking the address. To achieve zero-cost, the zcpointer library can be compiled with or without the `ZCPOINTER_TRACK_REFS` option. When disabled, `zc::owned` is just a type alias for `std::unique_ptr` diff --git a/test.cc b/test.cc index e8cbdf2..c519322 100644 --- a/test.cc +++ b/test.cc @@ -16,15 +16,9 @@ #include #include +#include "test_helpers.h" #include "zcpointer.h" -class C { - public: - ~C() {} - - void DoThing() {} -}; - class TestFailure : public std::logic_error { public: using std::logic_error::logic_error; @@ -169,6 +163,34 @@ void TestVector() { EXPECT_UAF(ref->DoThing()); } +void TestStack() { + zc::ref rc; + { + zc::member c; + rc = &c; + EXPECT(rc == &c); + c->DoThing(); + } + EXPECT_UAF(rc->DoThing()); +} + +void TestMember() { + zc::ref ref; + zc::ref> vec_ref; + { + X x("hello world"); + ref = x.c(); + vec_ref = x.vec_c(); + + vec_ref->push_back(C()); + vec_ref->push_back(C()); + + vec_ref->at(1).DoThing(); + } + EXPECT_UAF(ref->DoThing()); + EXPECT_UAF(vec_ref->at(1).DoThing()); +} + #define TEST_FUNC(fn) { #fn , Test##fn } int main() { @@ -182,6 +204,8 @@ int main() { TEST_FUNC(Equality), TEST_FUNC(Nulls), TEST_FUNC(Vector), + TEST_FUNC(Stack), + TEST_FUNC(Member), }; bool passed = true; diff --git a/test_helpers.cc b/test_helpers.cc new file mode 100644 index 0000000..45cba9b --- /dev/null +++ b/test_helpers.cc @@ -0,0 +1,34 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_helpers.h" + +C::C() {} + +C::~C() {} + +void C::DoThing() {} + +X::X(const char* v) : foo_(v) {} + +X::~X() {} + +size_t X::GetCount() const { + return vec_c_->size(); +} + +std::string X::DoString() { + vec_c_->push_back(C()); + return foo_; +} diff --git a/test_helpers.h b/test_helpers.h new file mode 100644 index 0000000..d4062db --- /dev/null +++ b/test_helpers.h @@ -0,0 +1,49 @@ +// Copyright 2016 Google Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ZCPOINTER_TEST_HELPERS_H_ +#define ZCPOINTER_TEST_HELPERS_H_ + +#include +#include + +#include "zcpointer.h" + +class C { + public: + C(); + ~C(); + void DoThing(); +}; + +class X { + public: + X(const char* v); + ~X(); + + zc::ref c() { return &c_; } + + zc::ref> vec_c() { return &vec_c_; } + + size_t GetCount() const; + + std::string DoString(); + + private: + std::string foo_; + zc::member c_; + zc::member> vec_c_; +}; + +#endif // ZCPOINTER_TEST_HELPERS_H_ diff --git a/zcpointer.h b/zcpointer.h index b9bb511..9af37d6 100644 --- a/zcpointer.h +++ b/zcpointer.h @@ -12,10 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +#ifndef ZCPOINTER_ZCPOINTER_H_ +#define ZCPOINTER_ZCPOINTER_H_ + #include #include #include #include +#include namespace zc { @@ -166,6 +170,30 @@ class ref { owned* ptr_; }; +template +class member { + public: + template + explicit member(Args&&... args) + : t_(new T(std::forward(args)...)) { + } + + ref operator&() { + return t_.get(); + } + + T* operator->() { + return t_.operator->(); + } + + const T* operator->() const { + return t_.operator->(); + } + + private: + owned t_; +}; + #else template @@ -174,6 +202,22 @@ using owned = std::unique_ptr; template using ref = T*; +template +class member : public T { + public: + using T::T; + + T* operator->() { + return this; + } + + const T* operator->() const { + return this; + } +}; + #endif } // namespace zc + +#endif // ZCPOINTER_ZCPOINTER_H_ -- 2.22.5