Skip to content

Commit 97cb3a8

Browse files
authored
Merge pull request #8444 from perezd/sync-stage
Integrate from Piper for C++, Java, and Python
2 parents f82e268 + 361308c commit 97cb3a8

File tree

11 files changed

+149
-83
lines changed

11 files changed

+149
-83
lines changed

CHANGES.txt

+3
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@ Unreleased Changes (C++/Java/Python/PHP/Objective-C/C#/Ruby/JavaScript)
2222
on an error path.
2323
* Avoid expensive inlined code space for encoding message length for messages
2424
>= 128 bytes and instead do a procedure call to a shared out-of-line routine.
25+
* util::DefaultFieldComparator will be final in a future version of protobuf.
26+
Subclasses should inherit from SimpleFieldComparator instead.
2527

2628
Java:
29+
* Detect invalid overflow of byteLimit and return InvalidProtocolBufferException as documented.
2730
* Exceptions thrown while reading from an InputStream in parseFrom are now
2831
included as causes.
2932
* Support potentially more efficient proto parsing from RopeByteStrings.
53 Bytes
Binary file not shown.

csharp/src/Google.Protobuf/Reflection/Descriptor.cs

+8-8
Original file line numberDiff line numberDiff line change
@@ -4796,11 +4796,11 @@ public void ClearJavaPackage() {
47964796

47974797
private string javaOuterClassname_;
47984798
/// <summary>
4799-
/// If set, all the classes from the .proto file are wrapped in a single
4800-
/// outer class with the given name. This applies to both Proto1
4801-
/// (equivalent to the old "--one_java_file" option) and Proto2 (where
4802-
/// a .proto always translates to a single class, but you may want to
4803-
/// explicitly choose the class name).
4799+
/// Controls the name of the wrapper Java class generated for the .proto file.
4800+
/// That class will always contain the .proto file's getDescriptor() method as
4801+
/// well as any top-level extensions defined in the .proto file.
4802+
/// If java_multiple_files is disabled, then all the other classes from the
4803+
/// .proto file will be nested inside the single wrapper outer class.
48044804
/// </summary>
48054805
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
48064806
public string JavaOuterClassname {
@@ -4826,10 +4826,10 @@ public void ClearJavaOuterClassname() {
48264826

48274827
private bool javaMultipleFiles_;
48284828
/// <summary>
4829-
/// If set true, then the Java code generator will generate a separate .java
4829+
/// If enabled, then the Java code generator will generate a separate .java
48304830
/// file for each top-level message, enum, and service defined in the .proto
4831-
/// file. Thus, these types will *not* be nested inside the outer class
4832-
/// named by java_outer_classname. However, the outer class will still be
4831+
/// file. Thus, these types will *not* be nested inside the wrapper class
4832+
/// named by java_outer_classname. However, the wrapper class will still be
48334833
/// generated to contain the file's getDescriptor() method as well as any
48344834
/// top-level extensions defined in the file.
48354835
/// </summary>

java/core/src/main/java/com/google/protobuf/CodedInputStream.java

+3
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,9 @@ public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
11851185
throw InvalidProtocolBufferException.negativeSize();
11861186
}
11871187
byteLimit += getTotalBytesRead();
1188+
if (byteLimit < 0) {
1189+
throw InvalidProtocolBufferException.parseFailure();
1190+
}
11881191
final int oldLimit = currentLimit;
11891192
if (byteLimit > oldLimit) {
11901193
throw InvalidProtocolBufferException.truncatedMessage();

java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java

+29
Original file line numberDiff line numberDiff line change
@@ -1284,4 +1284,33 @@ public synchronized int read(byte[] b, int off, int len) {
12841284
maliciousCapture.get(1)[0] = 0x9;
12851285
assertEquals(0x9, byteArray[0]); // MODIFICATION! Should we fix?
12861286
}
1287+
1288+
public void testInvalidInputYieldsInvalidProtocolBufferException_readTag() throws Exception {
1289+
byte[] input = new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x77};
1290+
CodedInputStream inputStream = CodedInputStream.newInstance(input);
1291+
try {
1292+
inputStream.readTag();
1293+
int size = inputStream.readRawVarint32();
1294+
inputStream.pushLimit(size);
1295+
inputStream.readTag();
1296+
fail();
1297+
} catch (InvalidProtocolBufferException ex) {
1298+
// Expected.
1299+
}
1300+
}
1301+
1302+
public void testInvalidInputYieldsInvalidProtocolBufferException_readBytes() throws Exception {
1303+
byte[] input =
1304+
new byte[] {0x0a, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 0x67, 0x1a, 0x1a};
1305+
CodedInputStream inputStream = CodedInputStream.newInstance(input);
1306+
try {
1307+
inputStream.readTag();
1308+
int size = inputStream.readRawVarint32();
1309+
inputStream.pushLimit(size);
1310+
inputStream.readBytes();
1311+
fail();
1312+
} catch (InvalidProtocolBufferException ex) {
1313+
// Expected.
1314+
}
1315+
}
12871316
}

php/src/Google/Protobuf/Internal/FileOptions.php

+32-32
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/google/protobuf/descriptor.proto

+8-8
Original file line numberDiff line numberDiff line change
@@ -348,17 +348,17 @@ message FileOptions {
348348
optional string java_package = 1;
349349

350350

351-
// If set, all the classes from the .proto file are wrapped in a single
352-
// outer class with the given name. This applies to both Proto1
353-
// (equivalent to the old "--one_java_file" option) and Proto2 (where
354-
// a .proto always translates to a single class, but you may want to
355-
// explicitly choose the class name).
351+
// Controls the name of the wrapper Java class generated for the .proto file.
352+
// That class will always contain the .proto file's getDescriptor() method as
353+
// well as any top-level extensions defined in the .proto file.
354+
// If java_multiple_files is disabled, then all the other classes from the
355+
// .proto file will be nested inside the single wrapper outer class.
356356
optional string java_outer_classname = 8;
357357

358-
// If set true, then the Java code generator will generate a separate .java
358+
// If enabled, then the Java code generator will generate a separate .java
359359
// file for each top-level message, enum, and service defined in the .proto
360-
// file. Thus, these types will *not* be nested inside the outer class
361-
// named by java_outer_classname. However, the outer class will still be
360+
// file. Thus, these types will *not* be nested inside the wrapper class
361+
// named by java_outer_classname. However, the wrapper class will still be
362362
// generated to contain the file's getDescriptor() method as well as any
363363
// top-level extensions defined in the file.
364364
optional bool java_multiple_files = 10 [default = false];

src/google/protobuf/port_undef.inc

+4
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@
7979
#undef PROTOBUF_ATTRIBUTE_INIT_PRIORITY
8080
#undef PROTOBUF_PRAGMA_INIT_SEG
8181

82+
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
83+
#undef PROTOBUF_FUTURE_BREAKING_CHANGES
84+
#endif
85+
8286
// Restore macro that may have been #undef'd in port_def.inc.
8387
#ifdef _MSC_VER
8488
#pragma pop_macro("CREATE_NEW")

src/google/protobuf/util/field_comparator.h

+7-10
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,6 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
146146
void SetDefaultFractionAndMargin(double fraction, double margin);
147147

148148
protected:
149-
// NOTE: this will go away.
150-
ComparisonResult Compare(const Message& message_1, const Message& message_2,
151-
const FieldDescriptor* field, int index_1,
152-
int index_2,
153-
const util::FieldContext* field_context) override {
154-
return SimpleCompare(message_1, message_2, field, index_1, index_2,
155-
field_context);
156-
}
157-
158149
// Returns the comparison result for the given field in two messages.
159150
//
160151
// This function is called directly by DefaultFieldComparator::Compare.
@@ -268,7 +259,13 @@ class PROTOBUF_EXPORT SimpleFieldComparator : public FieldComparator {
268259
};
269260

270261
// Default field comparison: use the basic implementation of FieldComparator.
271-
class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator {
262+
#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
263+
class PROTOBUF_EXPORT DefaultFieldComparator final
264+
: public SimpleFieldComparator
265+
#else // PROTOBUF_FUTURE_BREAKING_CHANGES
266+
class PROTOBUF_EXPORT DefaultFieldComparator : public SimpleFieldComparator
267+
#endif // PROTOBUF_FUTURE_BREAKING_CHANGES
268+
{
272269
public:
273270
ComparisonResult Compare(const Message& message_1, const Message& message_2,
274271
const FieldDescriptor* field, int index_1,

src/google/protobuf/util/message_differencer.cc

+41-24
Original file line numberDiff line numberDiff line change
@@ -148,18 +148,16 @@ class MessageDifferencer::MultipleFieldsMapKeyComparator
148148
const FieldDescriptor* field = key_field_path[path_index];
149149
std::vector<SpecificField> current_parent_fields(parent_fields);
150150
if (path_index == static_cast<int64_t>(key_field_path.size() - 1)) {
151-
if (field->is_repeated()) {
152-
if (!message_differencer_->CompareRepeatedField(
153-
message1, message2, field, &current_parent_fields)) {
154-
return false;
155-
}
151+
if (field->is_map()) {
152+
return message_differencer_->CompareMapField(message1, message2, field,
153+
&current_parent_fields);
154+
} else if (field->is_repeated()) {
155+
return message_differencer_->CompareRepeatedField(
156+
message1, message2, field, &current_parent_fields);
156157
} else {
157-
if (!message_differencer_->CompareFieldValueUsingParentFields(
158-
message1, message2, field, -1, -1, &current_parent_fields)) {
159-
return false;
160-
}
158+
return message_differencer_->CompareFieldValueUsingParentFields(
159+
message1, message2, field, -1, -1, &current_parent_fields);
161160
}
162-
return true;
163161
} else {
164162
const Reflection* reflection1 = message1.GetReflection();
165163
const Reflection* reflection2 = message2.GetReflection();
@@ -830,24 +828,17 @@ bool MessageDifferencer::CompareWithFieldsInternal(
830828

831829
bool fieldDifferent = false;
832830
assert(field1 != NULL);
833-
if (field1->is_repeated()) {
831+
if (field1->is_map()) {
832+
fieldDifferent =
833+
!CompareMapField(message1, message2, field1, parent_fields);
834+
} else if (field1->is_repeated()) {
834835
fieldDifferent =
835836
!CompareRepeatedField(message1, message2, field1, parent_fields);
836-
if (fieldDifferent) {
837-
if (reporter_ == NULL) return false;
838-
isDifferent = true;
839-
}
840837
} else {
841838
fieldDifferent = !CompareFieldValueUsingParentFields(
842839
message1, message2, field1, -1, -1, parent_fields);
843840

844-
// If we have found differences, either report them or terminate if
845-
// no reporter is present.
846-
if (fieldDifferent && reporter_ == NULL) {
847-
return false;
848-
}
849-
850-
if (reporter_ != NULL) {
841+
if (reporter_ != nullptr) {
851842
SpecificField specific_field;
852843
specific_field.field = field1;
853844
parent_fields->push_back(specific_field);
@@ -860,6 +851,10 @@ bool MessageDifferencer::CompareWithFieldsInternal(
860851
parent_fields->pop_back();
861852
}
862853
}
854+
if (fieldDifferent) {
855+
if (reporter_ == nullptr) return false;
856+
isDifferent = true;
857+
}
863858
// Increment the field indices.
864859
++field_index1;
865860
++field_index2;
@@ -1002,17 +997,19 @@ bool MessageDifferencer::CompareMapFieldByMapReflection(
1002997
return true;
1003998
}
1004999

1005-
bool MessageDifferencer::CompareRepeatedField(
1000+
bool MessageDifferencer::CompareMapField(
10061001
const Message& message1, const Message& message2,
10071002
const FieldDescriptor* repeated_field,
10081003
std::vector<SpecificField>* parent_fields) {
1004+
GOOGLE_DCHECK(repeated_field->is_map());
1005+
10091006
// the input FieldDescriptor is guaranteed to be repeated field.
10101007
const Reflection* reflection1 = message1.GetReflection();
10111008
const Reflection* reflection2 = message2.GetReflection();
10121009

10131010
// When both map fields are on map, do not sync to repeated field.
10141011
// TODO(jieluo): Add support for reporter
1015-
if (repeated_field->is_map() && reporter_ == nullptr &&
1012+
if (reporter_ == nullptr &&
10161013
// Users didn't set custom map field key comparator
10171014
map_field_key_comparator_.find(repeated_field) ==
10181015
map_field_key_comparator_.end() &&
@@ -1052,6 +1049,26 @@ bool MessageDifferencer::CompareRepeatedField(
10521049
}
10531050
}
10541051

1052+
return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
1053+
}
1054+
1055+
bool MessageDifferencer::CompareRepeatedField(
1056+
const Message& message1, const Message& message2,
1057+
const FieldDescriptor* repeated_field,
1058+
std::vector<SpecificField>* parent_fields) {
1059+
GOOGLE_DCHECK(!repeated_field->is_map());
1060+
return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
1061+
}
1062+
1063+
bool MessageDifferencer::CompareRepeatedRep(
1064+
const Message& message1, const Message& message2,
1065+
const FieldDescriptor* repeated_field,
1066+
std::vector<SpecificField>* parent_fields) {
1067+
// the input FieldDescriptor is guaranteed to be repeated field.
1068+
GOOGLE_DCHECK(repeated_field->is_repeated());
1069+
const Reflection* reflection1 = message1.GetReflection();
1070+
const Reflection* reflection2 = message2.GetReflection();
1071+
10551072
const int count1 = reflection1->FieldSize(message1, repeated_field);
10561073
const int count2 = reflection2->FieldSize(message2, repeated_field);
10571074
const bool treated_as_subset = IsTreatedAsSubset(repeated_field);

0 commit comments

Comments
 (0)