diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index a45d14b12..9270f3e69 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -900,6 +900,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS) : buf_(initial_size), finished_(false), + has_duplicate_keys_(false), flags_(flags), force_min_bit_width_(BIT_WIDTH_8), key_pool(KeyOffsetCompare(buf_)), @@ -1124,12 +1125,16 @@ class Builder FLATBUFFERS_FINAL_CLASS { auto bs = reinterpret_cast( flatbuffers::vector_data(buf_) + b.key.u_); auto comp = strcmp(as, bs); - // If this assertion hits, you've added two keys with the same - // value to this map. + // We want to disallow duplicate keys, since this results in a + // map where values cannot be found. + // But we can't assert here (since we don't want to fail on + // random JSON input) or have an error mechanism. + // Instead, we set has_duplicate_keys_ in the builder to + // signal this. // TODO: Have to check for pointer equality, as some sort // implementation apparently call this function with the same // element?? Why? - FLATBUFFERS_ASSERT(comp || &a == &b); + if (!comp && &a != &b) has_duplicate_keys_ = true; return comp < 0; }); // First create a vector out of all keys. @@ -1143,6 +1148,10 @@ class Builder FLATBUFFERS_FINAL_CLASS { return static_cast(vec.u_); } + // Call this after EndMap to see if the map had any duplicate keys. + // Any map with such keys won't be able to retrieve all values. + bool HasDuplicateKeys() const { return has_duplicate_keys_; } + template size_t Vector(F f) { auto start = StartVector(); f(); @@ -1574,6 +1583,7 @@ class Builder FLATBUFFERS_FINAL_CLASS { std::vector stack_; bool finished_; + bool has_duplicate_keys_; BuilderFlag flags_; diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 3f0407734..9800501dc 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2857,6 +2857,8 @@ CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) { }); ECHECK(err); builder->EndMap(start); + if (builder->HasDuplicateKeys()) + return Error("FlexBuffers map has duplicate keys"); break; } case '[': {