From 010ea126f3662c76e2d484e9710be2b8fcd53785 Mon Sep 17 00:00:00 2001
From: Daniel Cohen <daniel.cohen599@gmail.com>
Date: Sun, 25 Dec 2016 14:04:04 +0200
Subject: [PATCH 1/2] going to try clang_sanitize with libstdc++ with g++-6
 implementation

Conflicts:
	.travis.yml
	Makefile
---
 .travis.yml | 22 ++++++++++++++--------
 Makefile    |  3 ++-
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 006647ed..6bf2297e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -42,14 +42,20 @@ matrix:
       - make check TEST_PREFIX="valgrind --error-exitcode=1 --leak-check=full " TEST_PATTERN=""
 
   # cLang sanitizer
-
-  #- os: linux
-  #  env:
-  #    - LLVM_VERSION=3.8.1
-  #    - SPECIAL=sanitizer
-  #  compiler: clang
-  #  before_script:
-  #    - make clang_sanitize
+  # note: sadly clang's libc++ has errors when running with sanitize,
+  # so we use clang with gcc's libstdc++ which doesn't give those error.
+  # that's why we need to install g++-6 to get the lastest version
+  - os: linux
+    env:
+      - LLVM_VERSION=3.8.1
+      - SPECIAL=sanitizer
+    addons:
+      apt:
+        sources: ['ubuntu-toolchain-r-test']
+        packages: g++-6
+    compiler: clang
+    before_script:
+      - make clang_sanitize
 
   # cppcheck
 
diff --git a/Makefile b/Makefile
index e2c120db..c16d9d9b 100644
--- a/Makefile
+++ b/Makefile
@@ -92,8 +92,9 @@ fuzzing-stop:
 cppcheck:
 	cppcheck --enable=warning --inconclusive --force --std=c++11 src/json.hpp --error-exitcode=1
 
+# run clang sanitize (we are overrding the CXXFLAGS provided by travis in order to use gcc's libstdc++)
 clang_sanitize: clean
-	CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE)
+	CXX=clang++ CXXFLAGS="-g -O2 -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer" $(MAKE) check -C test
 
 
 ##########################################################################

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 2/2] #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;