| --- a/src/google/protobuf/descriptor.cc 2022-03-14 15:16:40.588943398 -0700 |
| +++ b/src/google/protobuf/descriptor.cc 2022-03-14 16:04:03.348461544 -0700 |
| @@ -4002,6 +4002,11 @@ |
| // Use its file as the parent instead. |
| if (parent == nullptr) parent = file_; |
| |
| + if (full_name.find('\0') != std::string::npos) { |
| + AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME, |
| + "\"" + full_name + "\" contains null character."); |
| + return false; |
| + } |
| if (tables_->AddSymbol(full_name, symbol)) { |
| if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) { |
| // This is only possible if there was already an error adding something of |
| @@ -4041,6 +4046,11 @@ |
| void DescriptorBuilder::AddPackage(const std::string& name, |
| const Message& proto, |
| const FileDescriptor* file) { |
| + if (name.find('\0') != std::string::npos) { |
| + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, |
| + "\"" + name + "\" contains null character."); |
| + return; |
| + } |
| if (tables_->AddSymbol(name, Symbol(file))) { |
| // Success. Also add parent package, if any. |
| std::string::size_type dot_pos = name.find_last_of('.'); |
| @@ -4354,6 +4364,12 @@ |
| } |
| result->pool_ = pool_; |
| |
| + if (result->name().find('\0') != std::string::npos) { |
| + AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME, |
| + "\"" + result->name() + "\" contains null character."); |
| + return nullptr; |
| + } |
| + |
| // Add to tables. |
| if (!tables_->AddFile(result)) { |
| AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, |
| --- a/src/google/protobuf/descriptor_unittest.cc 2020-02-14 12:13:20.000000000 -0800 |
| +++ b/src/google/protobuf/descriptor_unittest.cc 2022-03-14 15:18:13.727479837 -0700 |
| @@ -3765,6 +3765,45 @@ |
| "foo.proto: foo.$: NAME: \"$\" is not a valid identifier.\n"); |
| } |
| |
| +// 'str' is a static C-style string that may contain '\0' |
| +#define STATIC_STR(str) std::string((str), sizeof(str) - 1) |
| + |
| +TEST_F(ValidationErrorTest, NullCharSymbolName) { |
| + BuildFileWithErrors( |
| + "name: \"bar.proto\" " |
| + "package: \"foo\"" |
| + "message_type { " |
| + " name: '\\000\\001\\013.Bar' " |
| + " field { name: \"foo\" number: 9 label:LABEL_OPTIONAL type:TYPE_INT32 " |
| + "} " |
| + "}", |
| + STATIC_STR("bar.proto: foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a " |
| + "valid identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: " |
| + "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: " |
| + "foo.\0\x1\v.Bar: NAME: \"\0\x1\v.Bar\" is not a valid " |
| + "identifier.\nbar.proto: foo.\0\x1\v.Bar: NAME: " |
| + "\"\0\x1\v.Bar\" is not a valid identifier.\nbar.proto: " |
| + "foo.\0\x1\v.Bar.foo: NAME: \"foo.\0\x1\v.Bar.foo\" contains " |
| + "null character.\nbar.proto: foo.\0\x1\v.Bar: NAME: " |
| + "\"foo.\0\x1\v.Bar\" contains null character.\n")); |
| +} |
| + |
| +TEST_F(ValidationErrorTest, NullCharFileName) { |
| + BuildFileWithErrors( |
| + "name: \"bar\\000\\001\\013.proto\" " |
| + "package: \"outer.foo\"", |
| + STATIC_STR("bar\0\x1\v.proto: bar\0\x1\v.proto: NAME: " |
| + "\"bar\0\x1\v.proto\" contains null character.\n")); |
| +} |
| + |
| +TEST_F(ValidationErrorTest, NullCharPackageName) { |
| + BuildFileWithErrors( |
| + "name: \"bar.proto\" " |
| + "package: \"\\000\\001\\013.\"", |
| + STATIC_STR("bar.proto: \0\x1\v.: NAME: \"\0\x1\v.\" contains null " |
| + "character.\n")); |
| +} |
| + |
| TEST_F(ValidationErrorTest, MissingFileName) { |
| BuildFileWithErrors("", |
| |