nlohmann / nlohmann/json

basic_json destructor allocates memory, violating noexcept semantics

Open
#5,135 8 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kind: bug state: please discuss
Dominant language
C++
Stars
50.6k
Forks
7.5k
Avg merge
4d 17h
Merged PRs (30d)
58

Description

Description

The destructor of basic_json invokes json_value::destroy, which may allocate a large std::vector to flatten out its object/array hierarchy in order to avoid recursion. In the event of an allocation failure, the vector will throw an uncatchable std::bad_alloc, terminating the program.

(I noticed this while debugging a related issue, where destroying an invalidated JSON object caused a four-exabyte allocation.)

Reproduction steps
  • Create a complex JSON document by nesting a few million arrays/objects in an arbitrary structure.
  • Artificially exhaust the application's available memory.
  • Destroy your JSON document.
Expected vs. actual results

Allocating a bunch of memory in a destructor is weird and widely understood to be unsafe.

Normal recursive destruction would be suitable for my use-case. If that is unacceptable, there are methods (such as forming an ad-hoc linked list) that could be used to avoid recursion without allocating. If those methods are unacceptable, a non-throwing allocator could be used with a fallback to recursive destruction in the event that no memory is available.

The latter approach is implemented by PR #4654.

Minimal code example

Error messages

Compiler and operating system

Win11/MSVC

Library version

3.12.0

Validation

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading json_value::destroy and reviewing PR #4654, which the issue identifies as an implementation of one proposed approach. Check how destruction behaves when allocation fails, then compile and run the repository's unit tests. Done means basic_json destruction no longer performs a potentially throwing allocation or terminates on allocation failure.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.