From e4395a67a0d8a486311ab35ad01ee1e8fa29f968 Mon Sep 17 00:00:00 2001 From: csun5285 Date: Fri, 12 Dec 2025 17:36:27 +0800 Subject: [PATCH 1/2] [fix](json) Replace invalid JSONB with default JSONB null value --- be/src/util/jsonb_document.h | 12 ++++++++++++ be/test/vec/jsonb/jsonb_document_test.cpp | 15 +++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/be/src/util/jsonb_document.h b/be/src/util/jsonb_document.h index 9e3bdaed796363..77162a7951f599 100644 --- a/be/src/util/jsonb_document.h +++ b/be/src/util/jsonb_document.h @@ -1006,6 +1006,18 @@ struct ArrayVal : public ContainerVal { inline Status JsonbDocument::checkAndCreateDocument(const char* pb, size_t size, const JsonbDocument** doc) { *doc = nullptr; + if (!pb || size == 0) { + // Treat empty input as a valid JSONB null document. +#pragma pack(push, 1) + struct StaticNullJsonbDocument { + uint8_t ver; + JsonbType type; + }; +#pragma pack(pop) + static const StaticNullJsonbDocument kNullDoc {JSONB_VER, JsonbType::T_Null}; + *doc = reinterpret_cast(&kNullDoc); + return Status::OK(); + } if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) { return Status::InvalidArgument("Invalid JSONB document: too small size({}) or null pointer", size); diff --git a/be/test/vec/jsonb/jsonb_document_test.cpp b/be/test/vec/jsonb/jsonb_document_test.cpp index 56d0f5fa960141..e8bd380c883c21 100644 --- a/be/test/vec/jsonb/jsonb_document_test.cpp +++ b/be/test/vec/jsonb/jsonb_document_test.cpp @@ -279,4 +279,19 @@ TEST_F(JsonbDocumentTest, forobject) { } } +TEST_F(JsonbDocumentTest, invaild_jsonb_document) { + const JsonbDocument* doc = nullptr; + auto st = JsonbDocument::checkAndCreateDocument(nullptr, 0, &doc); + EXPECT_TRUE(st.ok()); + EXPECT_TRUE(doc != nullptr); + EXPECT_TRUE(doc->getValue()->isNull()); + + JsonbToJson jsonb_to_json; + std::string json_null = jsonb_to_json.to_json_string(doc->getValue()); + EXPECT_EQ(json_null, "null"); + + std::string json_string = JsonbToJson::jsonb_to_json_string(nullptr, 0); + EXPECT_EQ(json_null, json_string); +} + } // namespace doris \ No newline at end of file From e29252b596318c5ad6b736b4de17d1ee73251d9c Mon Sep 17 00:00:00 2001 From: csun5285 Date: Fri, 12 Dec 2025 19:53:25 +0800 Subject: [PATCH 2/2] fix comment --- be/src/util/jsonb_document.cpp | 38 ++++++++++++++++++++++++++++++++++ be/src/util/jsonb_document.h | 37 --------------------------------- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/be/src/util/jsonb_document.cpp b/be/src/util/jsonb_document.cpp index 2cebd3f2221279..55b12e0e9e6057 100644 --- a/be/src/util/jsonb_document.cpp +++ b/be/src/util/jsonb_document.cpp @@ -18,12 +18,50 @@ #include "jsonb_document.h" #include +#include #include #include "common/status.h" #include "util/jsonb_writer.h" namespace doris { + +Status JsonbDocument::checkAndCreateDocument(const char* pb, size_t size, + const JsonbDocument** doc) { + *doc = nullptr; + if (!pb || size == 0) { + static const std::string buf = []() { + JsonbWriter writer; + (void)writer.writeNull(); + auto* out = writer.getOutput(); + return std::string(out->getBuffer(), out->getSize()); + }(); + // Treat empty input as a valid JSONB null document. + *doc = reinterpret_cast(buf.data()); + return Status::OK(); + } + if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) { + return Status::InvalidArgument("Invalid JSONB document: too small size({}) or null pointer", + size); + } + + const auto* doc_ptr = (const JsonbDocument*)pb; + if (doc_ptr->header_.ver_ != JSONB_VER) { + return Status::InvalidArgument("Invalid JSONB document: invalid version({})", + doc_ptr->header_.ver_); + } + + const auto* val = (const JsonbValue*)doc_ptr->payload_; + if (val->type < JsonbType::T_Null || val->type >= JsonbType::NUM_TYPES || + size != sizeof(JsonbHeader) + val->numPackedBytes()) { + return Status::InvalidArgument("Invalid JSONB document: invalid type({}) or size({})", + static_cast(val->type), size); + } + + *doc = doc_ptr; + return Status::OK(); +} + JsonbFindResult JsonbValue::findValue(JsonbPath& path) const { JsonbFindResult result; bool is_wildcard = false; diff --git a/be/src/util/jsonb_document.h b/be/src/util/jsonb_document.h index 77162a7951f599..0220794a483d94 100644 --- a/be/src/util/jsonb_document.h +++ b/be/src/util/jsonb_document.h @@ -1003,43 +1003,6 @@ struct ArrayVal : public ContainerVal { const_iterator end() const { return const_iterator((pointer)(payload + size)); } }; -inline Status JsonbDocument::checkAndCreateDocument(const char* pb, size_t size, - const JsonbDocument** doc) { - *doc = nullptr; - if (!pb || size == 0) { - // Treat empty input as a valid JSONB null document. -#pragma pack(push, 1) - struct StaticNullJsonbDocument { - uint8_t ver; - JsonbType type; - }; -#pragma pack(pop) - static const StaticNullJsonbDocument kNullDoc {JSONB_VER, JsonbType::T_Null}; - *doc = reinterpret_cast(&kNullDoc); - return Status::OK(); - } - if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) { - return Status::InvalidArgument("Invalid JSONB document: too small size({}) or null pointer", - size); - } - - const auto* doc_ptr = (const JsonbDocument*)pb; - if (doc_ptr->header_.ver_ != JSONB_VER) { - return Status::InvalidArgument("Invalid JSONB document: invalid version({})", - doc_ptr->header_.ver_); - } - - const auto* val = (const JsonbValue*)doc_ptr->payload_; - if (val->type < JsonbType::T_Null || val->type >= JsonbType::NUM_TYPES || - size != sizeof(JsonbHeader) + val->numPackedBytes()) { - return Status::InvalidArgument("Invalid JSONB document: invalid type({}) or size({})", - static_cast(val->type), size); - } - - *doc = doc_ptr; - return Status::OK(); -} - inline const JsonbValue* JsonbDocument::createValue(const char* pb, size_t size) { if (!pb || size < sizeof(JsonbHeader) + sizeof(JsonbValue)) { return nullptr;