From ff3221a37573e3313d52d46fd3b94ec658ff66e8 Mon Sep 17 00:00:00 2001
From: Daniel Cohen <daniel.cohen599@gmail.com>
Date: Sun, 25 Dec 2016 22:52:37 +0200
Subject: [PATCH] #394 fixed memory leak in unit-allocator, found by clang's
 fsanitize

---
 test/src/unit-allocator.cpp | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/test/src/unit-allocator.cpp b/test/src/unit-allocator.cpp
index 25fd3349..c439c1c3 100644
--- a/test/src/unit-allocator.cpp
+++ b/test/src/unit-allocator.cpp
@@ -111,6 +111,16 @@ struct my_allocator : std::allocator<T>
     }
 };
 
+// allows deletion of raw pointer, usually hold by json_value
+template<class T>
+void my_allocator_clean_up(T* p)
+{
+    assert(p != nullptr);
+    my_allocator<T> alloc;
+    alloc.destroy(p);
+    alloc.deallocate(p, 1);
+}
+
 TEST_CASE("controlled bad_alloc")
 {
     // create JSON type using the throwing allocator
@@ -131,7 +141,8 @@ TEST_CASE("controlled bad_alloc")
             {
                 next_construct_fails = false;
                 auto t = my_json::value_t::object;
-                CHECK_NOTHROW(my_json::json_value j(t));
+                auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.object); };
+                CHECK_NOTHROW(my_json::json_value j(t); clean_up(j));
                 next_construct_fails = true;
                 CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
                 next_construct_fails = false;
@@ -140,7 +151,8 @@ TEST_CASE("controlled bad_alloc")
             {
                 next_construct_fails = false;
                 auto t = my_json::value_t::array;
-                CHECK_NOTHROW(my_json::json_value j(t));
+                auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.array); };
+                CHECK_NOTHROW(my_json::json_value j(t); clean_up(j));
                 next_construct_fails = true;
                 CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
                 next_construct_fails = false;
@@ -149,7 +161,8 @@ TEST_CASE("controlled bad_alloc")
             {
                 next_construct_fails = false;
                 auto t = my_json::value_t::string;
-                CHECK_NOTHROW(my_json::json_value j(t));
+                auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); };
+                CHECK_NOTHROW(my_json::json_value j(t); clean_up(j));
                 next_construct_fails = true;
                 CHECK_THROWS_AS(my_json::json_value j(t), std::bad_alloc);
                 next_construct_fails = false;
@@ -160,7 +173,8 @@ TEST_CASE("controlled bad_alloc")
         {
             next_construct_fails = false;
             my_json::string_t v("foo");
-            CHECK_NOTHROW(my_json::json_value j(v));
+            auto clean_up = [](my_json::json_value& j){ my_allocator_clean_up(j.string); };
+            CHECK_NOTHROW(my_json::json_value j(v); clean_up(j));
             next_construct_fails = true;
             CHECK_THROWS_AS(my_json::json_value j(v), std::bad_alloc);
             next_construct_fails = false;