diff --git a/include/flatbuffers/flexbuffers.h b/include/flatbuffers/flexbuffers.h index 5c42a7ed47..6a5e936996 100644 --- a/include/flatbuffers/flexbuffers.h +++ b/include/flatbuffers/flexbuffers.h @@ -1007,9 +1007,16 @@ inline Reference Map::operator[](const std::string& key) const { inline Reference GetRoot(const uint8_t* buffer, size_t size) { // See Finish() below for the serialization counterpart of this. // The root starts at the end of the buffer, so we parse backwards from there. + // A valid buffer needs at least 3 bytes: one for the root value, one for the + // packed type, and one for the byte width. + if (size < 3) return Reference(nullptr, 1, 0); auto end = buffer + size; auto byte_width = *--end; auto packed_type = *--end; + if (byte_width == 0 || byte_width > 8 || + static_cast(end - buffer) < byte_width) { + return Reference(nullptr, 1, 0); + } end -= byte_width; // The root data item. return Reference(end, byte_width, packed_type); } diff --git a/tests/fuzzer/flexbuffers_parser_fuzzer.cc b/tests/fuzzer/flexbuffers_parser_fuzzer.cc new file mode 100644 index 0000000000..1d400f2fde --- /dev/null +++ b/tests/fuzzer/flexbuffers_parser_fuzzer.cc @@ -0,0 +1,69 @@ +// Copyright 2026 Google LLC. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Fuzz target for FlexBuffers accessor methods on unverified buffers. +// This complements flexbuffers_verifier_fuzzer.cc (which only tests +// VerifyBuffer) by exercising the GetRoot/Reference code paths that +// callers may reach without prior verification. + +#include +#include +#include + +#include "flatbuffers/flexbuffers.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + auto root = flexbuffers::GetRoot(data, size); + + // Exercise the type-dispatch accessors that read from the buffer. + (void)root.GetType(); + (void)root.IsNull(); + (void)root.AsBool(); + (void)root.AsInt64(); + (void)root.AsUInt64(); + (void)root.AsDouble(); + (void)root.AsString().c_str(); + + if (root.IsVector()) { + auto vec = root.AsVector(); + for (size_t i = 0; i < vec.size() && i < 8; i++) { + (void)vec[i].AsInt64(); + } + } + + if (root.IsMap()) { + auto map = root.AsMap(); + auto keys = map.Keys(); + for (size_t i = 0; i < keys.size() && i < 8; i++) { + (void)keys[i].AsKey(); + } + } + + if (root.IsTypedVector()) { + auto tv = root.AsTypedVector(); + for (size_t i = 0; i < tv.size() && i < 8; i++) { + (void)tv[i].AsInt64(); + } + } + + if (root.IsBlob()) { + auto blob = root.AsBlob(); + (void)blob.size(); + (void)blob.data(); + } + + (void)root.ToString(); + + return 0; +}