nlohmann / json

JSON for Modern C++

Home Page:https://json.nlohmann.me

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ordered json pointer corruption

mishase opened this issue · comments

Description

When using ordered json with push_back call, pointer to previous structure gets corrupted

Reproduction steps

Use the code bellow with nlohmann::ordered_json to get corrupted pointer

Expected vs. actual results

Expected output (same code, without ordered json):

string
string
{"a":{"b":"test"},"c":[1]}

Actual output (corrupted pointer):

string
number
{"a":{"b":"test"},"c":[1]}

Minimal code example

#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::ordered_json; // use nlohmann::json to get correct result

int main()
{
	auto obj = json::parse("{\"a\": {\"b\": \"test\"}}");
		
	auto& ref = obj["a"]["b"];
	std::cout << ref.type_name() << '\n'; // string

	obj["c"] = json::array();
	obj["c"].push_back(1);

	std::cout << ref.type_name() << '\n'; // expected string, got number

	std::cout << obj.dump(); // valid result, {"a":{"b":"test"},"c":[1]}
}

Error messages

No response

Compiler and operating system

Tested on ARM Windows and X64 Windows in Debug and Release modes

Library version

3.11.3

Validation

This seems related to #4279.

As in the linked issue, you can't do that. The push_back function on vector can invalidate pointers, and ordered_json uses a vector.

It is related to the issue you mentioned earlier, but it's certainly NOT a documentation issue. ordered_json must have working push_back function without any pointer corruption or this function must be private if it can cause such behaviour. Please fix this

I have no idea how to fix it, so documentation is currently all we can do.

@mishase This behavior comes from std::vector<>::push_back(), so not only is it not broken, it is standards conforming.

https://en.cppreference.com/w/cpp/container/vector/push_back

If after the operation the new size() is greater than old capacity() a reallocation takes place, in which case all iterators (including the end() iterator) and all references to the elements are invalidated. Otherwise only the end() iterator is invalidated.