Browse Source

Possible double free fixed (#146).

main
offa 6 years ago
parent
commit
6ffc328198
3 changed files with 36 additions and 1 deletions
  1. +4
    -1
      include/unique_resource.h
  2. +23
    -0
      test/CallMocks.h
  3. +9
    -0
      test/UniqueResourceTest.cpp

+ 4
- 1
include/unique_resource.h View File

&& std::is_nothrow_move_constructible_v<D>) && std::is_nothrow_move_constructible_v<D>)
: resource(std::move_if_noexcept(other.resource.get()), scope_exit{[] { }}), : resource(std::move_if_noexcept(other.resource.get()), scope_exit{[] { }}),
deleter(std::move_if_noexcept(other.deleter.get()), scope_exit{[&other] { deleter(std::move_if_noexcept(other.deleter.get()), scope_exit{[&other] {
other.get_deleter()(other.resource.get());
if( other.execute_on_reset == true )
{
other.get_deleter()(other.resource.get());
}
other.release(); }}), other.release(); }}),
execute_on_reset(std::exchange(other.execute_on_reset, false)) execute_on_reset(std::exchange(other.execute_on_reset, false))
{ {

+ 23
- 0
test/CallMocks.h View File

CopyMock(const CopyMock&) { } CopyMock(const CopyMock&) { }
}; };


struct ConditionalThrowOnCopyDeleter
{
ConditionalThrowOnCopyDeleter() { }

ConditionalThrowOnCopyDeleter(const ConditionalThrowOnCopyDeleter&)
{
if( throwOnNextCopy == true )
{
throw std::exception{};
}
throwOnNextCopy = false;
}

MAKE_CONST_MOCK1(deleter, void(Handle));

void operator()(Handle h) const
{
this->deleter(h);
}

static inline bool throwOnNextCopy{false};
};

} }



+ 9
- 0
test/UniqueResourceTest.cpp View File

[[maybe_unused]] auto guard = std::move(movedFrom); [[maybe_unused]] auto guard = std::move(movedFrom);
} }


TEST_CASE("move-construction prevents double release", "[UniqueResource]")
{
auto movedFrom = sr::unique_resource{Handle{3}, ConditionalThrowOnCopyDeleter{}};
movedFrom.release();
ConditionalThrowOnCopyDeleter::throwOnNextCopy = true;

REQUIRE_THROWS([&movedFrom] { [[maybe_unused]] auto guard = std::move(movedFrom); }());
}

TEST_CASE("move assignment calls deleter", "[UniqueResource]") TEST_CASE("move assignment calls deleter", "[UniqueResource]")
{ {
auto moveFrom = sr::unique_resource{Handle{3}, deleter}; auto moveFrom = sr::unique_resource{Handle{3}, deleter};

Loading…
Cancel
Save