@@ -1387,6 +1387,217 @@ TEST_F(DescriptorTest, AbslStringifyWorks) {
13871387}
13881388
13891389
1390+ static void ExtendStringTo(std::string* str, int size) {
1391+ ABSL_CHECK_LE(str->size(), size);
1392+ str->replace(0, 0, size - str->size(), 'x');
1393+ ABSL_CHECK_EQ(str->size(), size);
1394+ }
1395+
1396+ static void TestBuildFileOnNameLimits(const FileDescriptorProto& proto,
1397+ std::string* str, int limit,
1398+ absl::string_view error) {
1399+ // Builds correctly.
1400+ {
1401+ ExtendStringTo(str, limit);
1402+ DescriptorPool pool;
1403+ MockErrorCollector error_collector;
1404+ EXPECT_NE(pool.BuildFileCollectingErrors(proto, &error_collector), nullptr);
1405+ EXPECT_EQ(error_collector.text_, "");
1406+ }
1407+
1408+ ExtendStringTo(str, limit + 1);
1409+ DescriptorPool pool;
1410+ MockErrorCollector error_collector;
1411+ EXPECT_EQ(pool.BuildFileCollectingErrors(proto, &error_collector), nullptr);
1412+ // Fails with the expected error.
1413+ EXPECT_THAT(error_collector.text_, HasSubstr(error));
1414+ }
1415+
1416+ static FileDescriptorProto MakeFile(absl::string_view in) {
1417+ FileDescriptorProto proto;
1418+ ABSL_CHECK(TextFormat::ParseFromString(in, &proto));
1419+ return proto;
1420+ }
1421+
1422+ TEST_F(DescriptorTest, AllSymbolNamesHaveLengthLimits) {
1423+ auto limits = internal::NameLimits();
1424+ FileDescriptorProto proto;
1425+
1426+ // This limit comes from how AllocateNames is implemented and the math for
1427+ // that leaks below.
1428+ // Ideally we would have hard and predictable limits on each kind of symbol
1429+ // instead.
1430+ constexpr int kNamesImplLimit = std::numeric_limits<uint16_t>::max();
1431+
1432+ // FileDescriptor::package
1433+ proto = MakeFile(R"pb(name: "foo.proto" package: "Package")pb");
1434+ TestBuildFileOnNameLimits(proto, proto.mutable_package(), limits.kPackageName,
1435+ "Package name is too long");
1436+
1437+ // Descriptor::name
1438+ proto = MakeFile(R"pb(name: "foo.proto"
1439+ message_type { name: "Message" })pb");
1440+ TestBuildFileOnNameLimits(proto,
1441+ proto.mutable_message_type(0)->mutable_name(),
1442+ kNamesImplLimit, "Name too long");
1443+ // Descriptor::full_name
1444+ proto = MakeFile(R"pb(name: "foo.proto"
1445+ package: "Package"
1446+ message_type { name: "Message" })pb");
1447+ TestBuildFileOnNameLimits(
1448+ proto, proto.mutable_message_type(0)->mutable_name(),
1449+ kNamesImplLimit - proto.package().size() - 1, "Name too long");
1450+ // Descriptor::reserved_name
1451+ proto = MakeFile(
1452+ R"pb(name: "foo.proto"
1453+ package: "Package"
1454+ message_type { name: "Message" reserved_name: "Reserved" })pb");
1455+ TestBuildFileOnNameLimits(
1456+ proto, proto.mutable_message_type(0)->mutable_reserved_name(0),
1457+ limits.kReservedName, "Reserved name too long");
1458+ // No FieldDescriptor::name, because that is always within a message.
1459+ // FieldDescriptor::full_name
1460+ proto = MakeFile(R"pb(name: "foo.proto"
1461+ package: "Package"
1462+ message_type {
1463+ name: "Message"
1464+ field { name: 'field' number: 1 type: TYPE_INT64 }
1465+ })pb");
1466+ TestBuildFileOnNameLimits(
1467+ proto, proto.mutable_message_type(0)->mutable_field(0)->mutable_name(),
1468+ kNamesImplLimit - proto.message_type(0).name().size() -
1469+ proto.package().size() - 2,
1470+ "Name too long");
1471+ // FieldDescriptor::json_name
1472+ proto = MakeFile(R"pb(name: "foo.proto"
1473+ package: "Package"
1474+ message_type {
1475+ name: "Message"
1476+ field {
1477+ name: 'field'
1478+ number: 1
1479+ type: TYPE_INT64
1480+ json_name: "other"
1481+ }
1482+ })pb");
1483+ TestBuildFileOnNameLimits(
1484+ proto,
1485+ proto.mutable_message_type(0)->mutable_field(0)->mutable_json_name(),
1486+ // the math here leaks the implementation details of AllocateFieldNames.
1487+ kNamesImplLimit - 3 * (1 + proto.message_type(0).field(0).name().size()) -
1488+ proto.message_type(0).name().size() - proto.package().size() - 3,
1489+ "Name too long");
1490+ // FieldDescriptor::name (extension)
1491+ proto = MakeFile(R"pb(name: "foo.proto"
1492+ message_type {
1493+ name: "Message"
1494+ extension_range { start: 1 end: 2 }
1495+ }
1496+ extension {
1497+ name: "extension"
1498+ number: 1
1499+ type: TYPE_INT32
1500+ extendee: "Message"
1501+ })pb");
1502+ TestBuildFileOnNameLimits(proto, proto.mutable_extension(0)->mutable_name(),
1503+ kNamesImplLimit - 1, "Name too long");
1504+ // FieldDescriptor::full_name (extension)
1505+ proto = MakeFile(R"pb(name: "foo.proto"
1506+ package: "Package"
1507+ message_type {
1508+ name: "Message"
1509+ extension_range { start: 1 end: 2 }
1510+ }
1511+ extension {
1512+ name: "extension"
1513+ number: 1
1514+ type: TYPE_INT32
1515+ extendee: "Message"
1516+ })pb");
1517+ TestBuildFileOnNameLimits(proto, proto.mutable_extension(0)->mutable_name(),
1518+ kNamesImplLimit - proto.package().size() - 1,
1519+ "Name too long");
1520+ // No OneofDescriptor::name, because that is always within a message.
1521+ // OneofDescriptor::full_name
1522+ proto = MakeFile(
1523+ R"pb(name: "foo.proto"
1524+ message_type {
1525+ name: "Message"
1526+ oneof_decl { name: "oneof" }
1527+ field { name: 'field' number: 1 type: TYPE_INT64 oneof_index: 0 }
1528+ }
1529+ )pb");
1530+ TestBuildFileOnNameLimits(
1531+ proto,
1532+ proto.mutable_message_type(0)->mutable_oneof_decl(0)->mutable_name(),
1533+ kNamesImplLimit - proto.message_type(0).name().size() - 1,
1534+ "Name too long");
1535+ // EnumDescriptor::name
1536+ proto = MakeFile(R"pb(name: "foo.proto"
1537+ enum_type {
1538+ name: "Enum"
1539+ value { name: "VALUE" number: 1 }
1540+ })pb");
1541+ TestBuildFileOnNameLimits(proto, proto.mutable_enum_type(0)->mutable_name(),
1542+ kNamesImplLimit, "Name too long");
1543+ // EnumDescriptor::full_name
1544+ proto = MakeFile(R"pb(name: "foo.proto"
1545+ package: "Package"
1546+ enum_type {
1547+ name: "Enum"
1548+ value { name: "VALUE" number: 1 }
1549+ })pb");
1550+ TestBuildFileOnNameLimits(proto, proto.mutable_enum_type(0)->mutable_name(),
1551+ kNamesImplLimit - proto.package().size() - 1,
1552+ "Name too long");
1553+ // EnumDescriptor::reserved_name
1554+ proto = MakeFile(R"pb(name: "foo.proto"
1555+ enum_type {
1556+ name: "Enum"
1557+ value { name: "VALUE" number: 1 }
1558+ reserved_name: "reserved"
1559+ })pb");
1560+ TestBuildFileOnNameLimits(
1561+ proto, proto.mutable_enum_type(0)->mutable_reserved_name(0),
1562+ limits.kReservedName, "Reserved name too long");
1563+ // EnumValueDescriptor::name
1564+ proto = MakeFile(R"pb(name: "foo.proto"
1565+ enum_type {
1566+ name: "Enum"
1567+ value { name: "VALUE" number: 1 }
1568+ })pb");
1569+ TestBuildFileOnNameLimits(
1570+ proto, proto.mutable_enum_type(0)->mutable_value(0)->mutable_name(),
1571+ kNamesImplLimit, "Name too long");
1572+ // EnumValueDescriptor::full_name
1573+ proto = MakeFile(R"pb(name: "foo.proto"
1574+ package: "Package"
1575+ enum_type {
1576+ name: "Enum"
1577+ value { name: "VALUE" number: 1 }
1578+ })pb");
1579+ TestBuildFileOnNameLimits(
1580+ proto, proto.mutable_enum_type(0)->mutable_value(0)->mutable_name(),
1581+ kNamesImplLimit - proto.package().size() - 1, "Name too long");
1582+ // ServiceDescriptor::full_name
1583+ proto = MakeFile(R"pb(name: "foo.proto"
1584+ package: "Package"
1585+ service { name: "Service" })pb");
1586+ TestBuildFileOnNameLimits(proto, proto.mutable_service(0)->mutable_name(),
1587+ kNamesImplLimit - proto.package().size() - 1,
1588+ "Name too long");
1589+ // MethodDescriptor::full_name
1590+ proto = MakeFile(R"pb(name: "foo.proto"
1591+ message_type { name: "M" }
1592+ service {
1593+ name: "Service"
1594+ method { name: "A" input_type: "M" output_type: "M" }
1595+ })pb");
1596+ TestBuildFileOnNameLimits(
1597+ proto, proto.mutable_service(0)->mutable_method(0)->mutable_name(),
1598+ kNamesImplLimit - proto.service(0).name().size() - 1, "Name too long");
1599+ }
1600+
13901601// ===================================================================
13911602
13921603// Test simple flat messages and fields.
0 commit comments