Merge tag 'refs/tags/sync-piper' into sync-stage

pull/8444/head
Derek Perez 4 years ago
commit 49ed194e88
  1. BIN
      csharp/src/Google.Protobuf.Test/testprotos.pb
  2. 16
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  3. 3
      java/core/src/main/java/com/google/protobuf/CodedInputStream.java
  4. 29
      java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
  5. 64
      php/src/Google/Protobuf/Internal/FileOptions.php
  6. 16
      src/google/protobuf/descriptor.proto
  7. 4
      src/google/protobuf/port_undef.inc
  8. 17
      src/google/protobuf/util/field_comparator.h
  9. 65
      src/google/protobuf/util/message_differencer.cc
  10. 15
      src/google/protobuf/util/message_differencer.h

@ -4796,11 +4796,11 @@ namespace Google.Protobuf.Reflection {
private string javaOuterClassname_; private string javaOuterClassname_;
/// <summary> /// <summary>
/// If set, all the classes from the .proto file are wrapped in a single /// Controls the name of the wrapper Java class generated for the .proto file.
/// outer class with the given name. This applies to both Proto1 /// That class will always contain the .proto file's getDescriptor() method as
/// (equivalent to the old "--one_java_file" option) and Proto2 (where /// well as any top-level extensions defined in the .proto file.
/// a .proto always translates to a single class, but you may want to /// If java_multiple_files is disabled, then all the other classes from the
/// explicitly choose the class name). /// .proto file will be nested inside the single wrapper outer class.
/// </summary> /// </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public string JavaOuterClassname { public string JavaOuterClassname {
@ -4826,10 +4826,10 @@ namespace Google.Protobuf.Reflection {
private bool javaMultipleFiles_; private bool javaMultipleFiles_;
/// <summary> /// <summary>
/// If set true, then the Java code generator will generate a separate .java /// If enabled, then the Java code generator will generate a separate .java
/// file for each top-level message, enum, and service defined in the .proto /// file for each top-level message, enum, and service defined in the .proto
/// file. Thus, these types will *not* be nested inside the outer class /// file. Thus, these types will *not* be nested inside the wrapper class
/// named by java_outer_classname. However, the outer class will still be /// named by java_outer_classname. However, the wrapper class will still be
/// generated to contain the file's getDescriptor() method as well as any /// generated to contain the file's getDescriptor() method as well as any
/// top-level extensions defined in the file. /// top-level extensions defined in the file.
/// </summary> /// </summary>

@ -1185,6 +1185,9 @@ public abstract class CodedInputStream {
throw InvalidProtocolBufferException.negativeSize(); throw InvalidProtocolBufferException.negativeSize();
} }
byteLimit += getTotalBytesRead(); byteLimit += getTotalBytesRead();
if (byteLimit < 0) {
throw InvalidProtocolBufferException.parseFailure();
}
final int oldLimit = currentLimit; final int oldLimit = currentLimit;
if (byteLimit > oldLimit) { if (byteLimit > oldLimit) {
throw InvalidProtocolBufferException.truncatedMessage(); throw InvalidProtocolBufferException.truncatedMessage();

@ -1284,4 +1284,33 @@ public class CodedInputStreamTest extends TestCase {
maliciousCapture.get(1)[0] = 0x9; maliciousCapture.get(1)[0] = 0x9;
assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix? assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
} }
public void testInvalidInputYieldsInvalidProtocolBufferException_readTag() throws Exception {
byte[] input = new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x77};
CodedInputStream inputStream = CodedInputStream.newInstance(input);
try {
inputStream.readTag();
int size = inputStream.readRawVarint32();
inputStream.pushLimit(size);
inputStream.readTag();
fail();
} catch (InvalidProtocolBufferException ex) {
// Expected.
}
}
public void testInvalidInputYieldsInvalidProtocolBufferException_readBytes() throws Exception {
byte[] input =
new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x67, 0x1a, 0x1a};
CodedInputStream inputStream = CodedInputStream.newInstance(input);
try {
inputStream.readTag();
int size = inputStream.readRawVarint32();
inputStream.pushLimit(size);
inputStream.readBytes();
fail();
} catch (InvalidProtocolBufferException ex) {
// Expected.
}
}
} }

@ -25,20 +25,20 @@ class FileOptions extends \Google\Protobuf\Internal\Message
*/ */
protected $java_package = null; protected $java_package = null;
/** /**
* If set, all the classes from the .proto file are wrapped in a single * Controls the name of the wrapper Java class generated for the .proto file.
* outer class with the given name. This applies to both Proto1 * That class will always contain the .proto file's getDescriptor() method as
* (equivalent to the old "--one_java_file" option) and Proto2 (where * well as any top-level extensions defined in the .proto file.
* a .proto always translates to a single class, but you may want to * If java_multiple_files is disabled, then all the other classes from the
* explicitly choose the class name). * .proto file will be nested inside the single wrapper outer class.
* *
* Generated from protobuf field <code>optional string java_outer_classname = 8;</code> * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
*/ */
protected $java_outer_classname = null; protected $java_outer_classname = null;
/** /**
* If set true, then the Java code generator will generate a separate .java * If enabled, then the Java code generator will generate a separate .java
* file for each top-level message, enum, and service defined in the .proto * file for each top-level message, enum, and service defined in the .proto
* file. Thus, these types will *not* be nested inside the outer class * file. Thus, these types will *not* be nested inside the wrapper class
* named by java_outer_classname. However, the outer class will still be * named by java_outer_classname. However, the wrapper class will still be
* generated to contain the file's getDescriptor() method as well as any * generated to contain the file's getDescriptor() method as well as any
* top-level extensions defined in the file. * top-level extensions defined in the file.
* *
@ -192,16 +192,16 @@ class FileOptions extends \Google\Protobuf\Internal\Message
* inappropriate because proto packages do not normally start with backwards * inappropriate because proto packages do not normally start with backwards
* domain names. * domain names.
* @type string $java_outer_classname * @type string $java_outer_classname
* If set, all the classes from the .proto file are wrapped in a single * Controls the name of the wrapper Java class generated for the .proto file.
* outer class with the given name. This applies to both Proto1 * That class will always contain the .proto file's getDescriptor() method as
* (equivalent to the old "--one_java_file" option) and Proto2 (where * well as any top-level extensions defined in the .proto file.
* a .proto always translates to a single class, but you may want to * If java_multiple_files is disabled, then all the other classes from the
* explicitly choose the class name). * .proto file will be nested inside the single wrapper outer class.
* @type bool $java_multiple_files * @type bool $java_multiple_files
* If set true, then the Java code generator will generate a separate .java * If enabled, then the Java code generator will generate a separate .java
* file for each top-level message, enum, and service defined in the .proto * file for each top-level message, enum, and service defined in the .proto
* file. Thus, these types will *not* be nested inside the outer class * file. Thus, these types will *not* be nested inside the wrapper class
* named by java_outer_classname. However, the outer class will still be * named by java_outer_classname. However, the wrapper class will still be
* generated to contain the file's getDescriptor() method as well as any * generated to contain the file's getDescriptor() method as well as any
* top-level extensions defined in the file. * top-level extensions defined in the file.
* @type bool $java_generate_equals_and_hash * @type bool $java_generate_equals_and_hash
@ -319,11 +319,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message
} }
/** /**
* If set, all the classes from the .proto file are wrapped in a single * Controls the name of the wrapper Java class generated for the .proto file.
* outer class with the given name. This applies to both Proto1 * That class will always contain the .proto file's getDescriptor() method as
* (equivalent to the old "--one_java_file" option) and Proto2 (where * well as any top-level extensions defined in the .proto file.
* a .proto always translates to a single class, but you may want to * If java_multiple_files is disabled, then all the other classes from the
* explicitly choose the class name). * .proto file will be nested inside the single wrapper outer class.
* *
* Generated from protobuf field <code>optional string java_outer_classname = 8;</code> * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
* @return string * @return string
@ -344,11 +344,11 @@ class FileOptions extends \Google\Protobuf\Internal\Message
} }
/** /**
* If set, all the classes from the .proto file are wrapped in a single * Controls the name of the wrapper Java class generated for the .proto file.
* outer class with the given name. This applies to both Proto1 * That class will always contain the .proto file's getDescriptor() method as
* (equivalent to the old "--one_java_file" option) and Proto2 (where * well as any top-level extensions defined in the .proto file.
* a .proto always translates to a single class, but you may want to * If java_multiple_files is disabled, then all the other classes from the
* explicitly choose the class name). * .proto file will be nested inside the single wrapper outer class.
* *
* Generated from protobuf field <code>optional string java_outer_classname = 8;</code> * Generated from protobuf field <code>optional string java_outer_classname = 8;</code>
* @param string $var * @param string $var
@ -363,10 +363,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
} }
/** /**
* If set true, then the Java code generator will generate a separate .java * If enabled, then the Java code generator will generate a separate .java
* file for each top-level message, enum, and service defined in the .proto * file for each top-level message, enum, and service defined in the .proto
* file. Thus, these types will *not* be nested inside the outer class * file. Thus, these types will *not* be nested inside the wrapper class
* named by java_outer_classname. However, the outer class will still be * named by java_outer_classname. However, the wrapper class will still be
* generated to contain the file's getDescriptor() method as well as any * generated to contain the file's getDescriptor() method as well as any
* top-level extensions defined in the file. * top-level extensions defined in the file.
* *
@ -389,10 +389,10 @@ class FileOptions extends \Google\Protobuf\Internal\Message
} }
/** /**
* If set true, then the Java code generator will generate a separate .java * If enabled, then the Java code generator will generate a separate .java
* file for each top-level message, enum, and service defined in the .proto * file for each top-level message, enum, and service defined in the .proto
* file. Thus, these types will *not* be nested inside the outer class * file. Thus, these types will *not* be nested inside the wrapper class
* named by java_outer_classname. However, the outer class will still be * named by java_outer_classname. However, the wrapper class will still be
* generated to contain the file's getDescriptor() method as well as any * generated to contain the file's getDescriptor() method as well as any
* top-level extensions defined in the file. * top-level extensions defined in the file.
* *

@ -348,17 +348,17 @@ message FileOptions {
optional string java_package = 1; optional string java_package = 1;
// If set, all the classes from the .proto file are wrapped in a single // Controls the name of the wrapper Java class generated for the .proto file.
// outer class with the given name. This applies to both Proto1 // That class will always contain the .proto file's getDescriptor() method as
// (equivalent to the old "--one_java_file" option) and Proto2 (where // well as any top-level extensions defined in the .proto file.
// a .proto always translates to a single class, but you may want to // If java_multiple_files is disabled, then all the other classes from the
// explicitly choose the class name). // .proto file will be nested inside the single wrapper outer class.
optional string java_outer_classname = 8; optional string java_outer_classname = 8;
// If set true, then the Java code generator will generate a separate .java // If enabled, then the Java code generator will generate a separate .java
// file for each top-level message, enum, and service defined in the .proto // file for each top-level message, enum, and service defined in the .proto
// file. Thus, these types will *not* be nested inside the outer class // file. Thus, these types will *not* be nested inside the wrapper class
// named by java_outer_classname. However, the outer class will still be // named by java_outer_classname. However, the wrapper class will still be
// generated to contain the file's getDescriptor() method as well as any // generated to contain the file's getDescriptor() method as well as any
// top-level extensions defined in the file. // top-level extensions defined in the file.
optional bool java_multiple_files = 10 [default = false]; optional bool java_multiple_files = 10 [default = false];

@ -79,6 +79,10 @@
#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY #undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
#undef PROTOBUF_PRAGMA_INIT_SEG #undef PROTOBUF_PRAGMA_INIT_SEG
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
#undef PROTOBUF_FUTURE_BREAKING_CHANGES
#endif
// Restore macro that may have been #undef'd in port_def.inc. // Restore macro that may have been #undef'd in port_def.inc.
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma pop_macro("CREATE_NEW") #pragma pop_macro("CREATE_NEW")

@ -146,15 +146,6 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
void SetDefaultFractionAndMargin(double fraction, double margin); void SetDefaultFractionAndMargin(double fraction, double margin);
protected: protected:
// NOTE: this will go away.
ComparisonResult Compare(const Message& message_1, const Message& message_2,
const FieldDescriptor* field, int index_1,
int index_2,
const util::FieldContext* field_context) override {
return SimpleCompare(message_1, message_2, field, index_1, index_2,
field_context);
}
// Returns the comparison result for the given field in two messages. // Returns the comparison result for the given field in two messages.
// //
// This function is called directly by DefaultFieldComparator::Compare. // This function is called directly by DefaultFieldComparator::Compare.
@ -268,7 +259,13 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
}; };
// Default field comparison: use the basic implementation of FieldComparator. // Default field comparison: use the basic implementation of FieldComparator.
class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator { #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
class PROTOBUF_EXPORT DefaultFieldComparator final
: public SimpleFieldComparator
#else // PROTOBUF_FUTURE_BREAKING_CHANGES
class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
{
public: public:
ComparisonResult Compare(const Message& message_1, const Message& message_2, ComparisonResult Compare(const Message& message_1, const Message& message_2,
const FieldDescriptor* field, int index_1, const FieldDescriptor* field, int index_1,

@ -148,18 +148,16 @@ class MessageDifferencer::MultipleFieldsMapKeyComparator
const FieldDescriptor* field = key_field_path[path_index]; const FieldDescriptor* field = key_field_path[path_index];
std::vector<SpecificField> current_parent_fields(parent_fields); std::vector<SpecificField> current_parent_fields(parent_fields);
if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) { if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
if (field->is_repeated()) { if (field->is_map()) {
if (!message_differencer_->CompareRepeatedField( return message_differencer_->CompareMapField(message1, message2, field,
message1, message2, field, &current_parent_fields)) { &current_parent_fields);
return false; } else if (field->is_repeated()) {
} return message_differencer_->CompareRepeatedField(
message1, message2, field, &current_parent_fields);
} else { } else {
if (!message_differencer_->CompareFieldValueUsingParentFields( return message_differencer_->CompareFieldValueUsingParentFields(
message1, message2, field, -1, -1, &current_parent_fields)) { message1, message2, field, -1, -1, &current_parent_fields);
return false;
}
} }
return true;
} else { } else {
const Reflection* reflection1 = message1.GetReflection(); const Reflection* reflection1 = message1.GetReflection();
const Reflection* reflection2 = message2.GetReflection(); const Reflection* reflection2 = message2.GetReflection();
@ -830,24 +828,17 @@ bool MessageDifferencer::CompareWithFieldsInternal(
bool fieldDifferent = false; bool fieldDifferent = false;
assert(field1 != NULL); assert(field1 != NULL);
if (field1->is_repeated()) { if (field1->is_map()) {
fieldDifferent =
!CompareMapField(message1, message2, field1, parent_fields);
} else if (field1->is_repeated()) {
fieldDifferent = fieldDifferent =
!CompareRepeatedField(message1, message2, field1, parent_fields); !CompareRepeatedField(message1, message2, field1, parent_fields);
if (fieldDifferent) {
if (reporter_ == NULL) return false;
isDifferent = true;
}
} else { } else {
fieldDifferent = !CompareFieldValueUsingParentFields( fieldDifferent = !CompareFieldValueUsingParentFields(
message1, message2, field1, -1, -1, parent_fields); message1, message2, field1, -1, -1, parent_fields);
// If we have found differences, either report them or terminate if if (reporter_ != nullptr) {
// no reporter is present.
if (fieldDifferent && reporter_ == NULL) {
return false;
}
if (reporter_ != NULL) {
SpecificField specific_field; SpecificField specific_field;
specific_field.field = field1; specific_field.field = field1;
parent_fields->push_back(specific_field); parent_fields->push_back(specific_field);
@ -860,6 +851,10 @@ bool MessageDifferencer::CompareWithFieldsInternal(
parent_fields->pop_back(); parent_fields->pop_back();
} }
} }
if (fieldDifferent) {
if (reporter_ == nullptr) return false;
isDifferent = true;
}
// Increment the field indices. // Increment the field indices.
++field_index1; ++field_index1;
++field_index2; ++field_index2;
@ -1002,17 +997,19 @@ bool MessageDifferencer::CompareMapFieldByMapReflection(
return true; return true;
} }
bool MessageDifferencer::CompareRepeatedField( bool MessageDifferencer::CompareMapField(
const Message& message1, const Message& message2, const Message& message1, const Message& message2,
const FieldDescriptor* repeated_field, const FieldDescriptor* repeated_field,
std::vector<SpecificField>* parent_fields) { std::vector<SpecificField>* parent_fields) {
GOOGLE_DCHECK(repeated_field->is_map());
// the input FieldDescriptor is guaranteed to be repeated field. // the input FieldDescriptor is guaranteed to be repeated field.
const Reflection* reflection1 = message1.GetReflection(); const Reflection* reflection1 = message1.GetReflection();
const Reflection* reflection2 = message2.GetReflection(); const Reflection* reflection2 = message2.GetReflection();
// When both map fields are on map, do not sync to repeated field. // When both map fields are on map, do not sync to repeated field.
// TODO(jieluo): Add support for reporter // TODO(jieluo): Add support for reporter
if (repeated_field->is_map() && reporter_ == nullptr && if (reporter_ == nullptr &&
// Users didn't set custom map field key comparator // Users didn't set custom map field key comparator
map_field_key_comparator_.find(repeated_field) == map_field_key_comparator_.find(repeated_field) ==
map_field_key_comparator_.end() && map_field_key_comparator_.end() &&
@ -1052,6 +1049,26 @@ bool MessageDifferencer::CompareRepeatedField(
} }
} }
return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
}
bool MessageDifferencer::CompareRepeatedField(
const Message& message1, const Message& message2,
const FieldDescriptor* repeated_field,
std::vector<SpecificField>* parent_fields) {
GOOGLE_DCHECK(!repeated_field->is_map());
return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
}
bool MessageDifferencer::CompareRepeatedRep(
const Message& message1, const Message& message2,
const FieldDescriptor* repeated_field,
std::vector<SpecificField>* parent_fields) {
// the input FieldDescriptor is guaranteed to be repeated field.
GOOGLE_DCHECK(repeated_field->is_repeated());
const Reflection* reflection1 = message1.GetReflection();
const Reflection* reflection2 = message2.GetReflection();
const int count1 = reflection1->FieldSize(message1, repeated_field); const int count1 = reflection1->FieldSize(message1, repeated_field);
const int count2 = reflection2->FieldSize(message2, repeated_field); const int count2 = reflection2->FieldSize(message2, repeated_field);
const bool treated_as_subset = IsTreatedAsSubset(repeated_field); const bool treated_as_subset = IsTreatedAsSubset(repeated_field);

@ -779,7 +779,20 @@ class PROTOBUF_EXPORT MessageDifferencer {
const FieldDescriptor* field, const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields); std::vector<SpecificField>* parent_fields);
// Compare the map fields using map reflection instead of sync to repeated. // Compares map fields, and report the error.
bool CompareMapField(const Message& message1, const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields);
// Helper for CompareRepeatedField and CompareMapField: compares and reports
// differences element-wise. This is the implementation for non-map fields,
// and can also compare map fields by using the underlying representation.
bool CompareRepeatedRep(const Message& message1, const Message& message2,
const FieldDescriptor* field,
std::vector<SpecificField>* parent_fields);
// Helper for CompareMapField: compare the map fields using map reflection
// instead of sync to repeated.
bool CompareMapFieldByMapReflection(const Message& message1, bool CompareMapFieldByMapReflection(const Message& message1,
const Message& message2, const Message& message2,
const FieldDescriptor* field, const FieldDescriptor* field,

Loading…
Cancel
Save