From 3973f80a9d9b41766e003ca31b21a0ebc90e23fc Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Thu, 17 Jan 2013 22:19:30 +0000 Subject: [PATCH] base: fix a nasty double free issue in Array::Remove(). --- src/lol/base/array.h | 4 +--- test/unit/array.cpp | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/lol/base/array.h b/src/lol/base/array.h index 7cde3086..9294dbe7 100644 --- a/src/lol/base/array.h +++ b/src/lol/base/array.h @@ -163,8 +163,6 @@ public: void Remove(int pos, int todelete = 1) { - /* FIXME: we need to call dtors for the first - * todelete elements here */ for (int i = pos; i + todelete < m_count; i++) m_data[i] = m_data[i + todelete]; for (int i = m_count - todelete; i < m_count; i++) @@ -182,7 +180,7 @@ public: /* Not enough elements? Add some. */ for (int i = m_count; i < count; ++i) - m_data[i] = e; + new(&m_data[i]) Element(e); m_count = count; } diff --git a/test/unit/array.cpp b/test/unit/array.cpp index 8afc6436..cc572f45 100644 --- a/test/unit/array.cpp +++ b/test/unit/array.cpp @@ -18,6 +18,18 @@ namespace lol { +struct TrackedObj +{ + static int m_ctor, m_dtor; + + TrackedObj() { m_ctor++; } + TrackedObj(TrackedObj const &) { m_ctor++; } + ~TrackedObj() { m_dtor++; } +}; + +int TrackedObj::m_ctor = 0; +int TrackedObj::m_dtor = 0; + LOLUNIT_FIXTURE(ArrayTest) { void SetUp() {} @@ -119,6 +131,31 @@ LOLUNIT_FIXTURE(ArrayTest) LOLUNIT_ASSERT_EQUAL(b[2], 2); LOLUNIT_ASSERT_EQUAL(b[3], 3); } + + LOLUNIT_TEST(ElementCtorDtor) + { + /* Ensure array elements get created and destroyed the proper + * number of times. */ + TrackedObj::m_ctor = 0; + TrackedObj::m_dtor = 0; + { + Array a; + + a.Push(TrackedObj()); + } + LOLUNIT_ASSERT_EQUAL(TrackedObj::m_ctor, TrackedObj::m_dtor); + + TrackedObj::m_ctor = 0; + TrackedObj::m_dtor = 0; + { + Array a; + + a.Resize(2); + a.Resize(4); + a.Resize(1); + } + LOLUNIT_ASSERT_EQUAL(TrackedObj::m_ctor, TrackedObj::m_dtor); + } }; } /* namespace lol */