From 47e47d6e9f29ce7fc92ccac3b970e00497815b33 Mon Sep 17 00:00:00 2001 From: Yamil Morales Date: Wed, 2 Sep 2026 12:49:48 -0700 Subject: [PATCH] Do not cache dynamic descriptors in FuzzTest's static descriptor cache. PiperOrigin-RevId: 975274331 --- .../arbitrary_domains_protobuf_test.cc | 30 +++++++++++++ .../internal/domains/protobuf_domain_impl.h | 44 ++++++++++++------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/domain_tests/arbitrary_domains_protobuf_test.cc b/domain_tests/arbitrary_domains_protobuf_test.cc index a770b0116..85aae8fb3 100644 --- a/domain_tests/arbitrary_domains_protobuf_test.cc +++ b/domain_tests/arbitrary_domains_protobuf_test.cc @@ -38,8 +38,10 @@ #include "./domain_tests/domain_testing.h" #include "./fuzztest/internal/test_protobuf.pb.h" #include "google/protobuf/descriptor.h" +#include "google/protobuf/dynamic_message.h" #include "google/protobuf/message.h" #include "google/protobuf/message_lite.h" +#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/util/message_differencer.h" namespace fuzztest { @@ -853,5 +855,33 @@ TEST(ProtobufDomainTest, LastMaxSizeSettingWins) { EXPECT_TRUE(domain2.ValidateCorpusValue(*corpus2).ok()); } +TEST(ProtobufDomainTest, EnsureNoUseAfterFreeAcrossDynamicPoolDestructions) { + google::protobuf::FileDescriptorProto file_proto; + file_proto.set_name("dynamic_test.proto"); + auto* message_proto = file_proto.add_message_type(); + message_proto->set_name("DynamicTestMessage"); + auto* field = message_proto->add_field(); + field->set_name("dynamic_field"); + field->set_number(1); + field->set_type(google::protobuf::FieldDescriptorProto::TYPE_INT32); + + for (int i = 0; i < 10; ++i) { + google::protobuf::DescriptorPool pool; + const google::protobuf::FileDescriptor* file_desc = pool.BuildFile(file_proto); + ASSERT_NE(file_desc, nullptr); + const google::protobuf::Descriptor* message_desc = + file_desc->FindMessageTypeByName("DynamicTestMessage"); + ASSERT_NE(message_desc, nullptr); + + google::protobuf::DynamicMessageFactory factory(&pool); + const google::protobuf::Message* prototype = factory.GetPrototype(message_desc); + ASSERT_NE(prototype, nullptr); + + auto domain = ProtobufOf([prototype] { return prototype; }); + auto values = GenerateInitialValues(domain, 10); + EXPECT_FALSE(values.empty()); + } +} + } // namespace } // namespace fuzztest diff --git a/fuzztest/internal/domains/protobuf_domain_impl.h b/fuzztest/internal/domains/protobuf_domain_impl.h index 39f45e2f8..c3e3ca502 100644 --- a/fuzztest/internal/domains/protobuf_domain_impl.h +++ b/fuzztest/internal/domains/protobuf_domain_impl.h @@ -364,31 +364,45 @@ class ProtoPolicy { return caches_->SetFields(descriptor, GetProtobufFields(descriptor)); } - static const std::vector& GetProtobufFields( + static std::vector GetProtobufFields( const ProtoDescriptor* descriptor) { - ABSL_CONST_INIT static absl::Mutex mutex(absl::kConstInit); - static absl::NoDestructor>>> - descriptor_to_fields ABSL_GUARDED_BY(mutex); - { + const auto* pool = descriptor->file()->pool(); + const bool is_generated_pool = (pool == pool->generated_pool()); + if (is_generated_pool) { + ABSL_CONST_INIT static absl::Mutex mutex(absl::kConstInit); + static absl::NoDestructor>>> + descriptor_to_fields ABSL_GUARDED_BY(mutex); + { + absl::MutexLock l(mutex); + auto it = descriptor_to_fields->find(descriptor); + if (it != descriptor_to_fields->end()) return *(it->second); + } + std::vector fields; + fields.reserve(descriptor->field_count()); + for (int i = 0; i < descriptor->field_count(); ++i) { + fields.push_back(descriptor->field(i)); + } absl::MutexLock l(mutex); - auto it = descriptor_to_fields->find(descriptor); - if (it != descriptor_to_fields->end()) return *(it->second); + if (ShouldEnumerateExtensions(descriptor)) { + pool->FindAllExtensions(descriptor, &fields); + } + auto [it, _] = descriptor_to_fields->insert( + {descriptor, std::make_unique>( + std::move(fields))}); + return *(it->second); } + std::vector fields; fields.reserve(descriptor->field_count()); for (int i = 0; i < descriptor->field_count(); ++i) { fields.push_back(descriptor->field(i)); } - absl::MutexLock l(mutex); if (ShouldEnumerateExtensions(descriptor)) { - descriptor->file()->pool()->FindAllExtensions(descriptor, &fields); + pool->FindAllExtensions(descriptor, &fields); } - auto [it, _] = descriptor_to_fields->insert( - {descriptor, std::make_unique>( - std::move(fields))}); - return *(it->second); + return fields; } private: