mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 18:35:46 +02:00
fix: json.merge exception crash (#3409)
json.merge would throw an exception when the json object did not contain the element to replace because RecursiveMerge functions used &dest->at(k_v.key()) which threw the exception. Remove RecursiveMerge completely and use the one implemented in jsoncons lib. * add test * replace RecursiveMerge with mergepatch::apply_merge_patch * add exception handling for that flow --------- Signed-off-by: kostas <kostas@dragonflydb.io>
This commit is contained in:
parent
558a22d5b8
commit
7e911c100a
2 changed files with 16 additions and 23 deletions
|
@ -13,6 +13,7 @@
|
|||
#include <jsoncons_ext/jsonpatch/jsonpatch.hpp>
|
||||
#include <jsoncons_ext/jsonpath/jsonpath.hpp>
|
||||
#include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
|
||||
#include <jsoncons_ext/mergepatch/mergepatch.hpp>
|
||||
|
||||
#include "base/flags.h"
|
||||
#include "base/logging.h"
|
||||
|
@ -1450,28 +1451,6 @@ OpStatus OpMSet(const OpArgs& op_args, const ShardArgs& args) {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Implements the recursive algorithm from
|
||||
// https://datatracker.ietf.org/doc/html/rfc7386#section-2
|
||||
void RecursiveMerge(const JsonType& patch, JsonType* dest) {
|
||||
if (!patch.is_object()) {
|
||||
*dest = patch;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dest->is_object()) {
|
||||
*dest = JsonType(json_object_arg, dest->get_allocator());
|
||||
}
|
||||
|
||||
for (const auto& k_v : patch.object_range()) {
|
||||
if (k_v.value().is_null()) {
|
||||
dest->erase(k_v.key());
|
||||
} else {
|
||||
RecursiveMerge(k_v.value(), &dest->at(k_v.key()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpStatus OpMerge(const OpArgs& op_args, string_view key, std::string_view json_str) {
|
||||
std::optional<JsonType> parsed_json = JsonFromString(json_str);
|
||||
if (!parsed_json) {
|
||||
|
@ -1485,7 +1464,14 @@ OpStatus OpMerge(const OpArgs& op_args, string_view key, std::string_view json_s
|
|||
op_args.shard->search_indices()->RemoveDoc(key, op_args.db_cntx, it_res->it->second);
|
||||
|
||||
JsonType* obj = it_res->it->second.GetJson();
|
||||
RecursiveMerge(*parsed_json, obj);
|
||||
try {
|
||||
// https://datatracker.ietf.org/doc/html/rfc7386#section-2
|
||||
mergepatch::apply_merge_patch(*obj, *parsed_json);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_EVERY_T(ERROR, 1) << "Exception in OpMerge: " << e.what() << " with obj: " << *obj
|
||||
<< " and patch: " << *parsed_json;
|
||||
return OpStatus::INVALID_VALUE;
|
||||
}
|
||||
it_res->post_updater.Run();
|
||||
op_args.shard->search_indices()->AddDoc(key, op_args.db_cntx, it_res->it->second);
|
||||
return OpStatus::OK;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue