Describe the bug
The function merge_or_update in sorted_json_object.hpp overrides the wrong fields in the overload that takes rvalue reference. The overload that takes a const lvalue ref behaves as expected.
Source code link for latest commit to the file at the time of opening this bug:
|
void merge_or_update(const sorted_json_object& source) |
|
{ |
|
for (auto it = source.begin(); it != source.end(); ++it) |
|
{ |
|
insert_or_assign((*it).key(),(*it).value()); |
|
} |
|
} |
|
|
|
void merge_or_update(sorted_json_object&& source) |
|
{ |
|
auto it = std::make_move_iterator(source.begin()); |
|
auto end = std::make_move_iterator(source.end()); |
|
for (; it != end; ++it) |
|
{ |
|
auto pos = std::lower_bound(data_.begin(),data_.end(), (*it).key(), |
|
Comp()); |
|
if (pos == data_.end()) |
|
{ |
|
data_.emplace_back(*it); |
|
} |
|
else |
|
{ |
|
pos->value((*it).value()); |
|
} |
|
} |
|
} |
The bug is that in the sorted_json_object&& overload, pos is searched using std::lower_bound, which returns the first element that should not appear before (*it).key(), but it does not check that it is actually that key before updating it.
For example, if I have a json object { "a": 5, "c": 19 } and I call merge_or_update with {"b":2} passed in a rvalue ref, the key b is not added to the json, rather the value of c changes to 2.
Again, the const sorted_json_object& behaves correctly.
merge_or_update should override the value of the correct key.
Passing an rvalue ref to merge_or_update removes existing keys if they don't exist in the input json.
Enumerate the steps to reproduce the bug
shown in example code
Include a small, self-contained example if possible
const jsoncons::json source = jsoncons::json::parse(R"({"b":2})");
jsoncons::json constRefTarget = jsoncons::json::parse(R"({"a":1,"c":3})");
constRefTarget.merge_or_update(source);
jsoncons::json rvalueTarget = jsoncons::json::parse(R"({"a":1,"c":3})");
rvalueTarget.merge_or_update(jsoncons::json(source));
std::cout << "expected: {\"a\":1,\"b\":2,\"c\":3}\n";
std::cout << "const&: " << constRefTarget << "\n";
std::cout << "&&: " << rvalueTarget << "\n";
Output:
expected: {"a":1,"b":2,"c":3}
const&: {"a":1,"b":2,"c":3}
&&: {"a":1,"c":2}
What compiler, architecture, and operating system?
Windows 11, x64, Visual Studio 18.10.1 build tools 14.51
- Compiler: MSVC
- Architecture (e.g. x86, x64) x64
- Operating system: Windows
What jsoncons library version?
Describe the bug
The function
merge_or_updateinsorted_json_object.hppoverrides the wrong fields in the overload that takes rvalue reference. The overload that takes a const lvalue ref behaves as expected.Source code link for latest commit to the file at the time of opening this bug:
jsoncons/include/jsoncons/sorted_json_object.hpp
Lines 647 to 672 in 4d28d41
The bug is that in the
sorted_json_object&&overload,posis searched usingstd::lower_bound, which returns the first element that should not appear before (*it).key(), but it does not check that it is actually that key before updating it.For example, if I have a json object
{ "a": 5, "c": 19 }and I callmerge_or_updatewith{"b":2}passed in a rvalue ref, the keybis not added to the json, rather the value ofcchanges to 2.Again, the
const sorted_json_object&behaves correctly.merge_or_updateshould override the value of the correct key.Passing an rvalue ref to
merge_or_updateremoves existing keys if they don't exist in the input json.Enumerate the steps to reproduce the bug
shown in example code
Include a small, self-contained example if possible
Output:
What compiler, architecture, and operating system?
Windows 11, x64, Visual Studio 18.10.1 build tools 14.51
What jsoncons library version?