Skip to content

Commit

Permalink
Fixes #1971 (memory leak in basic_json::push_back)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemSarmini committed Apr 2, 2020
1 parent 19843b0 commit e4d8dc0
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
4 changes: 1 addition & 3 deletions include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4878,9 +4878,7 @@ class basic_json

// add element to array (move semantics)
m_value.array->push_back(std::move(val));
// invalidate object: mark it null so we do not call the destructor
// cppcheck-suppress accessMoved
val.m_type = value_t::null;
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
}

/*!
Expand Down
4 changes: 1 addition & 3 deletions single_include/nlohmann/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19421,9 +19421,7 @@ class basic_json

// add element to array (move semantics)
m_value.array->push_back(std::move(val));
// invalidate object: mark it null so we do not call the destructor
// cppcheck-suppress accessMoved
val.m_type = value_t::null;
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
}

/*!
Expand Down
48 changes: 48 additions & 0 deletions test/src/unit-allocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,51 @@ TEST_CASE("controlled bad_alloc")
}
}
}

namespace
{
template<class T>
struct allocator_no_forward
{
typedef std::remove_const_t<T> value_type;
template <typename U>
struct rebind
{
typedef allocator_no_forward<U> other;
};

T* allocate(size_t sz)
{
return static_cast<T*>(malloc(sz * sizeof(T)));
}

void deallocate(T* p, size_t)
{
free(p);
}

void construct(T* p, const T& arg)
{
::new (static_cast<void*>(p)) T(arg);
}
};
}

TEST_CASE("bad my_allocator::construct")
{
SECTION("my_allocator::construct doesn't forward")
{
using bad_alloc_json = nlohmann::basic_json<std::map,
std::vector,
std::string,
bool,
std::int64_t,
std::uint64_t,
double,
allocator_no_forward>;

bad_alloc_json json;
json["test"] = bad_alloc_json::array_t();
json["test"].push_back("should not leak");
}
}

0 comments on commit e4d8dc0

Please sign in to comment.