Skip to content

Commit 90824aa

Browse files
mkruskal-googlecopybara-github
authored andcommitted
Fail early for messages with more than 65k fields.
This would already cause problems for any generated code, and C++ dynamic messages would overflow a uint16_t during parse. PiperOrigin-RevId: 794732114
1 parent e9a5f37 commit 90824aa

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

‎python/google/protobuf/internal/proto_builder_test.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def testMakeSameProtoClassTwice(self):
6666

6767
def testMakeLargeProtoClass(self):
6868
"""Test that large created protos don't use reserved field numbers."""
69-
num_fields = 123456
69+
num_fields = 65000
7070
fields = {
7171
'foo%d' % i: descriptor_pb2.FieldDescriptorProto.TYPE_INT64
7272
for i in range(num_fields)

‎src/google/protobuf/descriptor.cc‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ namespace google {
9696
namespace protobuf {
9797
namespace {
9898

99-
const int kPackageLimit = 100;
99+
constexpr int kPackageLimit = 100;
100+
constexpr int kMaxFieldsPerMessage = 65535;
100101

101102

102103
size_t CamelCaseSize(const absl::string_view input) {
@@ -6870,6 +6871,16 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
68706871
});
68716872
}
68726873
}
6874+
6875+
if (result->field_count() > kMaxFieldsPerMessage) {
6876+
AddError(
6877+
result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, [&] {
6878+
return absl::StrCat(result->field_count(), " fields in ",
6879+
result->full_name(), " exceeds the limit of ",
6880+
kMaxFieldsPerMessage);
6881+
});
6882+
}
6883+
68736884
// Check that fields aren't using reserved names or numbers and that they
68746885
// aren't using extension numbers.
68756886
for (int i = 0; i < result->field_count(); i++) {

‎src/google/protobuf/descriptor_unittest.cc‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13786,6 +13786,27 @@ TEST_F(ValidationErrorTest, PackageTooLong) {
1378613786
"aaaaaaaa: NAME: Package name is too long\n");
1378713787
}
1378813788

13789+
TEST_F(ValidationErrorTest, TooManyFieldsInMessage) {
13790+
FileDescriptorProto file = ParseTextOrDie(R"pb(
13791+
name: "foo.proto"
13792+
syntax: "proto2"
13793+
package: "test"
13794+
message_type { name: "Foo" }
13795+
)pb");
13796+
13797+
for (int i = 0; i < 70000; ++i) {
13798+
FieldDescriptorProto* field = file.mutable_message_type(0)->add_field();
13799+
field->set_name(absl::StrCat("field", i));
13800+
field->set_number(i + 1);
13801+
field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
13802+
field->set_type(FieldDescriptorProto::TYPE_INT32);
13803+
}
13804+
BuildFileWithErrors(
13805+
file,
13806+
"foo.proto: test.Foo: TYPE: 70000 fields in test.Foo exceeds the limit "
13807+
"of 65535\n");
13808+
}
13809+
1378913810

1379013811
// ===================================================================
1379113812
// DescriptorDatabase

0 commit comments

Comments
 (0)