Merge pull request #7464 from haberman/sync-stage

Integrate from Piper for C++, Java, and Python
pull/7476/head
Joshua Haberman 5 years ago committed by GitHub
commit 7eb207c574
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 11
      python/google/protobuf/internal/json_format_test.py
  2. 3
      python/google/protobuf/json_format.py
  3. 5
      src/google/protobuf/arena.cc
  4. 6
      src/google/protobuf/arena_impl.h
  5. 13
      src/google/protobuf/compiler/cpp/cpp_string_field.cc
  6. 1
      src/google/protobuf/compiler/cpp/cpp_string_field.h
  7. 20
      src/google/protobuf/compiler/cpp/cpp_unittest.inc
  8. 2
      src/google/protobuf/descriptor.cc
  9. 12
      src/google/protobuf/descriptor_unittest.cc
  10. 3
      src/google/protobuf/map.h
  11. 33
      src/google/protobuf/map_field.h
  12. 6
      src/google/protobuf/message.h
  13. 6
      src/google/protobuf/port_def.inc
  14. 1
      src/google/protobuf/port_undef.inc
  15. 62
      src/google/protobuf/reflection_ops.cc
  16. 2
      src/google/protobuf/reflection_ops.h
  17. 37
      src/google/protobuf/reflection_ops_unittest.cc
  18. 4
      src/google/protobuf/struct.pb.h
  19. 6
      src/google/protobuf/stubs/port.h
  20. 17
      src/google/protobuf/text_format.cc
  21. 30
      src/google/protobuf/text_format_unittest.cc
  22. 2
      src/google/protobuf/util/internal/default_value_objectwriter.h
  23. 2
      src/google/protobuf/util/internal/json_stream_parser.h
  24. 8
      src/google/protobuf/util/internal/json_stream_parser_test.cc
  25. 2
      src/google/protobuf/util/internal/protostream_objectsource.h
  26. 14
      src/google/protobuf/util/internal/protostream_objectsource_test.cc

@ -239,16 +239,19 @@ class JsonFormatTest(JsonFormatBase):
golden_dict = {
'messageSet': {
'[protobuf_unittest.'
'TestMessageSetExtension1.messageSetExtension]': {
'TestMessageSetExtension1.message_set_extension]': {
'i': 23,
},
'[protobuf_unittest.'
'TestMessageSetExtension2.messageSetExtension]': {
'TestMessageSetExtension2.message_set_extension]': {
'str': u'foo',
},
},
}
self.assertEqual(golden_dict, message_dict)
parsed_msg = unittest_mset_pb2.TestMessageSetContainer()
json_format.ParseDict(golden_dict, parsed_msg)
self.assertEqual(message, parsed_msg)
def testExtensionSerializationDictMatchesProto3SpecMore(self):
"""See go/proto3-json-spec for spec.
@ -279,9 +282,9 @@ class JsonFormatTest(JsonFormatBase):
message
)
ext1_text = ('protobuf_unittest.TestMessageSetExtension1.'
'messageSetExtension')
'message_set_extension')
ext2_text = ('protobuf_unittest.TestMessageSetExtension2.'
'messageSetExtension')
'message_set_extension')
golden_text = ('{"messageSet": {'
' "[%s]": {'
' "i": 23'

@ -246,8 +246,7 @@ class _Printer(object):
js[name] = [self._FieldToJsonObject(field, k)
for k in value]
elif field.is_extension:
full_qualifier = field.full_name[:-len(field.name)]
name = '[%s%s]' % (full_qualifier, name)
name = '[%s]' % field.full_name
js[name] = self._FieldToJsonObject(field, value)
else:
js[name] = self._FieldToJsonObject(field, value)

@ -59,11 +59,12 @@ ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
}
#elif defined(PROTOBUF_USE_DLLS)
ArenaImpl::ThreadCache& ArenaImpl::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL};
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_ = {-1, NULL};
return thread_cache_;
}
#else
GOOGLE_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1, NULL};
PROTOBUF_THREAD_LOCAL ArenaImpl::ThreadCache ArenaImpl::thread_cache_ = {-1,
NULL};
#endif
void ArenaImpl::Init() {

@ -288,16 +288,16 @@ class PROTOBUF_EXPORT ArenaImpl {
};
static std::atomic<LifecycleId> lifecycle_id_generator_;
#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
// Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread
// Android ndk does not support __thread keyword so we use a custom thread
// local storage class we implemented.
// iOS also does not support the GOOGLE_THREAD_LOCAL keyword.
// iOS also does not support the __thread keyword.
static ThreadCache& thread_cache();
#elif defined(PROTOBUF_USE_DLLS)
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static PROTOBUF_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
#endif

@ -754,6 +754,10 @@ void StringOneofFieldGenerator::GenerateInlineAccessorDefinitions(
" if ($name$ != nullptr) {\n"
" set_has_$name$();\n"
" $field_member$.UnsafeSetDefault($name$);\n"
" ::$proto_ns$::Arena* arena = GetArena();\n"
" if (arena != nullptr) {\n"
" arena->Own($name$);\n"
" }\n"
" }\n"
" // @@protoc_insertion_point(field_set_allocated:$full_name$)\n"
"}\n");
@ -917,15 +921,6 @@ void StringOneofFieldGenerator::GenerateConstructorCode(
" $default_variable$);\n");
}
void StringOneofFieldGenerator::GenerateDestructorCode(
io::Printer* printer) const {
Formatter format(printer, variables_);
format(
"if (_internal_has_$name$()) {\n"
" $field_member$.DestroyNoArena($default_variable$);\n"
"}\n");
}
// ===================================================================
RepeatedStringFieldGenerator::RepeatedStringFieldGenerator(

@ -95,7 +95,6 @@ class StringOneofFieldGenerator : public StringFieldGenerator {
void GenerateMessageClearingCode(io::Printer* printer) const;
void GenerateSwappingCode(io::Printer* printer) const;
void GenerateConstructorCode(io::Printer* printer) const;
void GenerateDestructorCode(io::Printer* printer) const;
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator);

@ -1683,6 +1683,26 @@ TEST_F(OneofTest, SetAllocatedString) {
EXPECT_EQ(kHello, message.foo_string());
}
TEST_F(OneofTest, ArenaSetAllocatedString) {
// Check that set_allocated_foo() works for strings.
Arena arena;
UNITTEST::TestOneof2* message =
Arena::CreateMessage<UNITTEST::TestOneof2>(&arena);
EXPECT_FALSE(message->has_foo_string());
const std::string kHello("hello");
message->set_foo_string(kHello);
EXPECT_TRUE(message->has_foo_string());
message->set_allocated_foo_string(NULL);
EXPECT_FALSE(message->has_foo_string());
EXPECT_EQ("", message->foo_string());
message->set_allocated_foo_string(new std::string(kHello));
EXPECT_TRUE(message->has_foo_string());
EXPECT_EQ(kHello, message->foo_string());
}
TEST_F(OneofTest, SetMessage) {
// Check that setting a message field works

@ -3522,7 +3522,7 @@ class DescriptorBuilder {
return pool->enforce_weak_;
}
static inline bool get_is_placeholder(const Descriptor* descriptor) {
return descriptor->is_placeholder_;
return descriptor != nullptr && descriptor->is_placeholder_;
}
static inline void assert_mutex_held(const DescriptorPool* pool) {
if (pool->mutex_ != nullptr) {

@ -2592,11 +2592,9 @@ TEST_F(MiscTest, DefaultValues) {
ASSERT_TRUE(message->field(10)->has_default_value());
EXPECT_EQ(-1, message->field(0)->default_value_int32());
EXPECT_EQ(-PROTOBUF_ULONGLONG(1000000000000),
message->field(1)->default_value_int64());
EXPECT_EQ(int64{-1000000000000}, message->field(1)->default_value_int64());
EXPECT_EQ(42, message->field(2)->default_value_uint32());
EXPECT_EQ(PROTOBUF_ULONGLONG(2000000000000),
message->field(3)->default_value_uint64());
EXPECT_EQ(uint64{2000000000000}, message->field(3)->default_value_uint64());
EXPECT_EQ(4.5, message->field(4)->default_value_float());
EXPECT_EQ(10e100, message->field(5)->default_value_double());
EXPECT_TRUE(message->field(6)->default_value_bool());
@ -3009,11 +3007,11 @@ TEST(CustomOptions, OptionLocations) {
file->FindServiceByName("TestServiceWithCustomOptions");
const MethodDescriptor* method = service->FindMethodByName("Foo");
EXPECT_EQ(PROTOBUF_LONGLONG(9876543210),
EXPECT_EQ(int64{9876543210},
file->options().GetExtension(protobuf_unittest::file_opt1));
EXPECT_EQ(-56,
message->options().GetExtension(protobuf_unittest::message_opt1));
EXPECT_EQ(PROTOBUF_LONGLONG(8765432109),
EXPECT_EQ(int64{8765432109},
field->options().GetExtension(protobuf_unittest::field_opt1));
EXPECT_EQ(42, // Check that we get the default for an option we don't set.
field->options().GetExtension(protobuf_unittest::field_opt2));
@ -3021,7 +3019,7 @@ TEST(CustomOptions, OptionLocations) {
EXPECT_EQ(-789, enm->options().GetExtension(protobuf_unittest::enum_opt1));
EXPECT_EQ(123, enm->value(1)->options().GetExtension(
protobuf_unittest::enum_value_opt1));
EXPECT_EQ(PROTOBUF_LONGLONG(-9876543210),
EXPECT_EQ(int64{-9876543210},
service->options().GetExtension(protobuf_unittest::service_opt1));
EXPECT_EQ(protobuf_unittest::METHODOPT1_VAL2,
method->options().GetExtension(protobuf_unittest::method_opt1));

@ -37,6 +37,7 @@
#ifndef GOOGLE_PROTOBUF_MAP_H__
#define GOOGLE_PROTOBUF_MAP_H__
#include <functional>
#include <initializer_list>
#include <iterator>
#include <limits> // To support Visual Studio 2008
@ -268,7 +269,7 @@ class Map {
using const_reference = const value_type&;
using size_type = size_t;
using hasher = hash<Key>;
using hasher = std::hash<Key>;
Map() : arena_(nullptr), default_enum_value_(0) { Init(); }
explicit Map(Arena* arena) : arena_(arena), default_enum_value_(0) { Init(); }

@ -32,6 +32,7 @@
#define GOOGLE_PROTOBUF_MAP_FIELD_H__
#include <atomic>
#include <functional>
#include <google/protobuf/arena.h>
#include <google/protobuf/descriptor.h>
@ -796,7 +797,7 @@ class PROTOBUF_EXPORT MapIterator {
} // namespace protobuf
} // namespace google
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
namespace std {
template <>
struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
size_t operator()(const ::PROTOBUF_NAMESPACE_ID::MapKey& map_key) const {
@ -809,16 +810,25 @@ struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
break;
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_STRING:
return hash<std::string>()(map_key.GetStringValue());
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64:
return hash<int64>()(map_key.GetInt64Value());
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32:
return hash<int32>()(map_key.GetInt32Value());
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64:
return hash<uint64>()(map_key.GetUInt64Value());
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32:
return hash<uint32>()(map_key.GetUInt32Value());
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL:
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT64: {
auto value = map_key.GetInt64Value();
return hash<decltype(value)>()(value);
}
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_INT32: {
auto value = map_key.GetInt32Value();
return hash<decltype(value)>()(map_key.GetInt32Value());
}
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT64: {
auto value = map_key.GetUInt64Value();
return hash<decltype(value)>()(map_key.GetUInt64Value());
}
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_UINT32: {
auto value = map_key.GetUInt32Value();
return hash<decltype(value)>()(map_key.GetUInt32Value());
}
case ::PROTOBUF_NAMESPACE_ID::FieldDescriptor::CPPTYPE_BOOL: {
return hash<bool>()(map_key.GetBoolValue());
}
}
GOOGLE_LOG(FATAL) << "Can't get here.";
return 0;
@ -828,8 +838,7 @@ struct hash<::PROTOBUF_NAMESPACE_ID::MapKey> {
return map_key1 < map_key2;
}
};
GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
} // namespace std
#include <google/protobuf/port_undef.inc>
#endif // GOOGLE_PROTOBUF_MAP_FIELD_H__

@ -1011,8 +1011,10 @@ class PROTOBUF_EXPORT Reflection final {
const OneofDescriptor* oneof_descriptor) const;
inline uint32* MutableOneofCase(
Message* message, const OneofDescriptor* oneof_descriptor) const;
inline const internal::ExtensionSet& GetExtensionSet(
const Message& message) const;
inline bool HasExtensionSet(const Message& message) const {
return schema_.HasExtensionSet();
}
const internal::ExtensionSet& GetExtensionSet(const Message& message) const;
internal::ExtensionSet* MutableExtensionSet(Message* message) const;
inline Arena* GetArena(Message* message) const;

@ -634,3 +634,9 @@ PROTOBUF_EXPORT_TEMPLATE_TEST(DEFAULT, __declspec(dllimport));
#endif
#define PROTOBUF_FINAL final
#if defined(_MSC_VER)
#define PROTOBUF_THREAD_LOCAL __declspec(thread)
#else
#define PROTOBUF_THREAD_LOCAL __thread
#endif

@ -83,6 +83,7 @@
#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllexport
#undef PROTOBUF_EXPORT_TEMPLATE_STYLE_MATCH_DECLSPEC_dllimport
#undef PROTOBUF_FINAL
#undef PROTOBUF_THREAD_LOCAL
// Restore macro that may have been #undef'd in port_def.inc.
#ifdef _MSC_VER

@ -188,6 +188,68 @@ void ReflectionOps::Clear(Message* message) {
reflection->MutableUnknownFields(message)->Clear();
}
bool ReflectionOps::IsInitialized(const Message& message, bool check_fields,
bool check_descendants) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = GetReflectionOrDie(message);
if (const int field_count = descriptor->field_count()) {
const FieldDescriptor* begin = descriptor->field(0);
const FieldDescriptor* end = begin + field_count;
GOOGLE_DCHECK_EQ(descriptor->field(field_count - 1), end - 1);
if (check_fields) {
// Check required fields of this message.
for (const FieldDescriptor* field = begin; field != end; ++field) {
if (field->is_required() && !reflection->HasField(message, field)) {
return false;
}
}
}
if (check_descendants) {
for (const FieldDescriptor* field = begin; field != end; ++field) {
if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
const Descriptor* message_type = field->message_type();
if (PROTOBUF_PREDICT_FALSE(message_type->options().map_entry())) {
if (message_type->field(1)->cpp_type() ==
FieldDescriptor::CPPTYPE_MESSAGE) {
const MapFieldBase* map_field =
reflection->GetMapData(message, field);
if (map_field->IsMapValid()) {
MapIterator it(const_cast<Message*>(&message), field);
MapIterator end(const_cast<Message*>(&message), field);
for (map_field->MapBegin(&it), map_field->MapEnd(&end);
it != end; ++it) {
if (!it.GetValueRef().GetMessageValue().IsInitialized()) {
return false;
}
}
}
}
} else if (field->is_repeated()) {
const int size = reflection->FieldSize(message, field);
for (int j = 0; j < size; j++) {
if (!reflection->GetRepeatedMessage(message, field, j)
.IsInitialized()) {
return false;
}
}
} else if (reflection->HasField(message, field)) {
if (!reflection->GetMessage(message, field).IsInitialized()) {
return false;
}
}
}
}
}
}
if (check_descendants && reflection->HasExtensionSet(message) &&
!reflection->GetExtensionSet(message).IsInitialized()) {
return false;
}
return true;
}
bool ReflectionOps::IsInitialized(const Message& message) {
const Descriptor* descriptor = message.GetDescriptor();
const Reflection* reflection = GetReflectionOrDie(message);

@ -66,6 +66,8 @@ class PROTOBUF_EXPORT ReflectionOps {
static void Merge(const Message& from, Message* to);
static void Clear(Message* message);
static bool IsInitialized(const Message& message);
static bool IsInitialized(const Message& message, bool check_fields,
bool check_descendants);
static void DiscardUnknownFields(Message* message);
// Finds all unset required fields in the message and adds their full

@ -340,12 +340,20 @@ TEST(ReflectionOpsTest, IsInitialized) {
unittest::TestRequired message;
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
message.set_a(1);
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
message.set_b(2);
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, true, true));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
message.set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
}
TEST(ReflectionOpsTest, ForeignIsInitialized) {
@ -354,26 +362,35 @@ TEST(ReflectionOpsTest, ForeignIsInitialized) {
// Starts out initialized because the foreign message is itself an optional
// field.
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
// Once we create that field, the message is no longer initialized.
message.mutable_optional_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
// Initialize it. Now we're initialized.
message.mutable_optional_message()->set_a(1);
message.mutable_optional_message()->set_b(2);
message.mutable_optional_message()->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
// Add a repeated version of the message. No longer initialized.
unittest::TestRequired* sub_message = message.add_repeated_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
// Initialize that repeated version.
sub_message->set_a(1);
sub_message->set_b(2);
sub_message->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
}
TEST(ReflectionOpsTest, ExtensionIsInitialized) {
@ -382,42 +399,62 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) {
// Starts out initialized because the foreign message is itself an optional
// field.
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
// Once we create that field, the message is no longer initialized.
message.MutableExtension(unittest::TestRequired::single);
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
// Initialize it. Now we're initialized.
message.MutableExtension(unittest::TestRequired::single)->set_a(1);
message.MutableExtension(unittest::TestRequired::single)->set_b(2);
message.MutableExtension(unittest::TestRequired::single)->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
// Add a repeated version of the message. No longer initialized.
message.AddExtension(unittest::TestRequired::multi);
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
// Initialize that repeated version.
message.MutableExtension(unittest::TestRequired::multi, 0)->set_a(1);
message.MutableExtension(unittest::TestRequired::multi, 0)->set_b(2);
message.MutableExtension(unittest::TestRequired::multi, 0)->set_c(3);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
}
TEST(ReflectionOpsTest, OneofIsInitialized) {
unittest::TestRequiredOneof message;
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
message.mutable_foo_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
message.set_foo_int(1);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
message.mutable_foo_message();
EXPECT_FALSE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_FALSE(ReflectionOps::IsInitialized(message, false, true));
message.mutable_foo_message()->set_required_double(0.1);
EXPECT_TRUE(ReflectionOps::IsInitialized(message));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, true, false));
EXPECT_TRUE(ReflectionOps::IsInitialized(message, false, true));
}
static std::string FindInitializationErrors(const Message& message) {

@ -911,6 +911,10 @@ inline void Value::set_allocated_string_value(std::string* string_value) {
if (string_value != nullptr) {
set_has_string_value();
kind_.string_value_.UnsafeSetDefault(string_value);
::PROTOBUF_NAMESPACE_ID::Arena* arena = GetArena();
if (arena != nullptr) {
arena->Own(string_value);
}
}
// @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value)
}

@ -225,12 +225,6 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2
#endif
#if defined(_MSC_VER)
#define GOOGLE_THREAD_LOCAL __declspec(thread)
#else
#define GOOGLE_THREAD_LOCAL __thread
#endif
// The following guarantees declaration of the byte swap functions.
#ifdef _MSC_VER
#define bswap_16(x) _byteswap_ushort(x)

@ -258,6 +258,7 @@ class TextFormat::Parser::ParserImpl {
allow_unknown_enum_(allow_unknown_enum),
allow_field_number_(allow_field_number),
allow_partial_(allow_partial),
initial_recursion_limit_(recursion_limit),
recursion_limit_(recursion_limit),
had_errors_(false) {
// For backwards-compatibility with proto1, we need to allow the 'f' suffix
@ -636,7 +637,10 @@ class TextFormat::Parser::ParserImpl {
bool ConsumeFieldMessage(Message* message, const Reflection* reflection,
const FieldDescriptor* field) {
if (--recursion_limit_ < 0) {
ReportError("Message is too deep");
ReportError(
StrCat("Message is too deep, the parser exceeded the "
"configured recursion limit of ",
initial_recursion_limit_, "."));
return false;
}
// If the parse information tree is not nullptr, create a nested one
@ -668,12 +672,22 @@ class TextFormat::Parser::ParserImpl {
// Skips the whole body of a message including the beginning delimiter and
// the ending delimiter.
bool SkipFieldMessage() {
if (--recursion_limit_ < 0) {
ReportError(
StrCat("Message is too deep, the parser exceeded the "
"configured recursion limit of ",
initial_recursion_limit_, "."));
return false;
}
std::string delimiter;
DO(ConsumeMessageDelimiter(&delimiter));
while (!LookingAt(">") && !LookingAt("}")) {
DO(SkipField());
}
DO(Consume(delimiter));
++recursion_limit_;
return true;
}
@ -1192,6 +1206,7 @@ class TextFormat::Parser::ParserImpl {
const bool allow_unknown_enum_;
const bool allow_field_number_;
const bool allow_partial_;
const int initial_recursion_limit_;
int recursion_limit_;
bool had_errors_;
};

@ -55,9 +55,9 @@
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
#include <google/protobuf/stubs/substitute.h>
#include <google/protobuf/port_def.inc>
@ -1911,7 +1911,33 @@ TEST_F(TextFormatParserTest, SetRecursionLimit) {
input = strings::Substitute(format, input);
parser_.SetRecursionLimit(100);
ExpectMessage(input, "Message is too deep", 1, 908, &message, false);
ExpectMessage(input,
"Message is too deep, the parser exceeded the configured "
"recursion limit of 100.",
1, 908, &message, false);
parser_.SetRecursionLimit(101);
ExpectSuccessAndTree(input, &message, nullptr);
}
TEST_F(TextFormatParserTest, SetRecursionLimitUnknownField) {
const char* format = "unknown_child: { $0 }";
std::string input;
for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input);
parser_.AllowUnknownField(true);
unittest::NestedTestAllTypes message;
ExpectSuccessAndTree(input, &message, nullptr);
input = strings::Substitute(format, input);
parser_.SetRecursionLimit(100);
ExpectMessage(
input,
"WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
"field named \"unknown_child\".\n1:1716: Message is too deep, the parser "
"exceeded the configured recursion limit of 100.",
1, 14, &message, false);
parser_.SetRecursionLimit(101);
ExpectSuccessAndTree(input, &message, nullptr);

@ -201,7 +201,7 @@ class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
// Returns the Value Type of a map given the Type of the map entry and a
// TypeInfo instance.
const google::protobuf::Type* GetMapValueType(
const google::protobuf::Type& entry_type, const TypeInfo* typeinfo);
const google::protobuf::Type& found_type, const TypeInfo* typeinfo);
// Calls WriteTo() on every child in children_.
void WriteChildren(ObjectWriter* ow);

@ -130,7 +130,7 @@ class PROTOBUF_EXPORT JsonStreamParser {
};
// Parses a single chunk of JSON, returning an error if the JSON was invalid.
util::Status ParseChunk(StringPiece json);
util::Status ParseChunk(StringPiece chunk);
// Runs the parser based on stack_ and p_, until the stack is empty or p_ runs
// out of data. If we unexpectedly run out of p_ we push the latest back onto

@ -235,7 +235,7 @@ TEST_F(JsonStreamParserTest, SimpleInt) {
TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
StringPiece str = "-79497823553162765";
for (int i = 0; i <= str.length(); ++i) {
ow_.RenderInt64("", -79497823553162765LL);
ow_.RenderInt64("", int64{-79497823553162765});
DoTest(str, i);
}
}
@ -243,7 +243,7 @@ TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
StringPiece str = "11779497823553162765";
for (int i = 0; i <= str.length(); ++i) {
ow_.RenderUint64("", 11779497823553162765ULL);
ow_.RenderUint64("", uint64{11779497823553162765u});
DoTest(str, i);
}
}
@ -378,7 +378,7 @@ TEST_F(JsonStreamParserTest, ArrayComplexValues) {
->RenderInt64("", -127)
->RenderDouble("", 45.3)
->RenderDouble("", -1056.4)
->RenderUint64("", 11779497823553162765ULL)
->RenderUint64("", uint64{11779497823553162765u})
->EndList()
->StartObject("")
->RenderBool("key", true)
@ -406,7 +406,7 @@ TEST_F(JsonStreamParserTest, ObjectValues) {
->RenderInt64("ni", -127)
->RenderDouble("pd", 45.3)
->RenderDouble("nd", -1056.4)
->RenderUint64("pl", 11779497823553162765ULL)
->RenderUint64("pl", uint64{11779497823553162765u})
->StartList("l")
->StartList("")
->EndList()

@ -131,7 +131,7 @@ class PROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource {
// nested messages (end with 0) and nested groups (end with group end tag).
// The include_start_and_end parameter allows this method to be called when
// already inside of an object, and skip calling StartObject and EndObject.
virtual util::Status WriteMessage(const google::protobuf::Type& descriptor,
virtual util::Status WriteMessage(const google::protobuf::Type& type,
StringPiece name,
const uint32 end_tag,
bool include_start_and_end,

@ -152,13 +152,13 @@ class ProtostreamObjectSourceTest
->RenderInt32("", 3208)
->EndList()
->StartList("repFix64")
->RenderUint64("", bit_cast<uint64>(6401LL))
->RenderUint64("", bit_cast<uint64>(0LL))
->RenderUint64("", bit_cast<uint64>(int64{6401}))
->RenderUint64("", bit_cast<uint64>(int64{0}))
->EndList()
->StartList("repU64")
->RenderUint64("", bit_cast<uint64>(0LL))
->RenderUint64("", bit_cast<uint64>(6402LL))
->RenderUint64("", bit_cast<uint64>(6403LL))
->RenderUint64("", bit_cast<uint64>(int64{0}))
->RenderUint64("", bit_cast<uint64>(int64{6402}))
->RenderUint64("", bit_cast<uint64>(int64{6403}))
->EndList()
->StartList("repI64")
->RenderInt64("", 6404L)
@ -325,8 +325,8 @@ TEST_P(ProtostreamObjectSourceTest, Primitives) {
->RenderInt32("i32", 3203)
->RenderInt32("sf32", 3204)
->RenderInt32("s32", 3205)
->RenderUint64("fix64", bit_cast<uint64>(6401LL))
->RenderUint64("u64", bit_cast<uint64>(6402LL))
->RenderUint64("fix64", bit_cast<uint64>(int64{6401}))
->RenderUint64("u64", bit_cast<uint64>(int64{6402}))
->RenderInt64("i64", 6403L)
->RenderInt64("sf64", 6404L)
->RenderInt64("s64", 6405L)

Loading…
Cancel
Save