Skip to content

Commit 8e3eca4

Browse files
thomasvlcopybara-github
authored andcommitted
[ObjC] Improve parsing validations
Pass through the expected end marker and validate it so calling code can't forget to do the validations. PiperOrigin-RevId: 651809006
1 parent b14d9ee commit 8e3eca4

File tree

5 files changed

+61
-71
lines changed

5 files changed

+61
-71
lines changed

objectivec/GPBCodedInputStream.m

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -429,9 +429,9 @@ - (void)readGroup:(int32_t)fieldNumber
429429
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
430430
CheckRecursionLimit(&state_);
431431
++state_.recursionDepth;
432-
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
433-
GPBCodedInputStreamCheckLastTagWas(&state_,
434-
GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
432+
[message mergeFromCodedInputStream:self
433+
extensionRegistry:extensionRegistry
434+
endingTag:GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)];
435435
--state_.recursionDepth;
436436
}
437437

@@ -452,8 +452,7 @@ - (void)readMessage:(GPBMessage *)message
452452
size_t length2 = (size_t)length; // Cast safe on 32bit because of CheckFieldSize() above.
453453
size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length2);
454454
++state_.recursionDepth;
455-
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
456-
GPBCodedInputStreamCheckLastTagWas(&state_, 0);
455+
[message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry endingTag:0];
457456
--state_.recursionDepth;
458457
GPBCodedInputStreamPopLimit(&state_, oldLimit);
459458
}

objectivec/GPBMessage.m

Lines changed: 52 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,9 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension,
746746
if (GPBExtensionIsWireFormat(description)) {
747747
// For MessageSet fields the message length will have already been
748748
// read.
749-
[targetMessage mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
749+
[targetMessage mergeFromCodedInputStream:input
750+
extensionRegistry:extensionRegistry
751+
endingTag:0];
750752
} else {
751753
[input readMessage:targetMessage extensionRegistry:extensionRegistry];
752754
}
@@ -1027,7 +1029,7 @@ - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
10271029
error:(NSError **)errorPtr {
10281030
if ((self = [self init])) {
10291031
@try {
1030-
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
1032+
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
10311033
if (errorPtr) {
10321034
*errorPtr = nil;
10331035
}
@@ -2078,8 +2080,7 @@ - (void)clearExtension:(GPBExtensionDescriptor *)extension {
20782080
- (void)mergeFromData:(NSData *)data extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
20792081
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
20802082
@try {
2081-
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
2082-
[input checkLastTagWas:0];
2083+
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
20832084
} @finally {
20842085
[input release];
20852086
}
@@ -2090,7 +2091,7 @@ - (BOOL)mergeFromData:(NSData *)data
20902091
error:(NSError **)errorPtr {
20912092
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
20922093
@try {
2093-
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
2094+
[self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry endingTag:0];
20942095
[input checkLastTagWas:0];
20952096
if (errorPtr) {
20962097
*errorPtr = nil;
@@ -2227,38 +2228,36 @@ - (void)parseMessageSet:(GPBCodedInputStream *)input
22272228
}
22282229
}
22292230

2230-
- (BOOL)parseUnknownField:(GPBCodedInputStream *)input
2231+
- (void)parseUnknownField:(GPBCodedInputStream *)input
22312232
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
22322233
tag:(uint32_t)tag {
2233-
GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
22342234
int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
2235-
22362235
GPBDescriptor *descriptor = [self descriptor];
22372236
GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor:descriptor
22382237
fieldNumber:fieldNumber];
22392238
if (extension == nil) {
22402239
if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
22412240
[self parseMessageSet:input extensionRegistry:extensionRegistry];
2242-
return YES;
2241+
return;
22432242
}
22442243
} else {
2244+
GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
22452245
if (extension.wireType == wireType) {
22462246
ExtensionMergeFromInputStream(extension, extension.packable, input, extensionRegistry, self);
2247-
return YES;
2247+
return;
22482248
}
22492249
// Primitive, repeated types can be packed on unpacked on the wire, and are
22502250
// parsed either way.
22512251
if ([extension isRepeated] && !GPBDataTypeIsObject(extension->description_->dataType) &&
22522252
(extension.alternateWireType == wireType)) {
22532253
ExtensionMergeFromInputStream(extension, !extension.packable, input, extensionRegistry, self);
2254-
return YES;
2254+
return;
22552255
}
22562256
}
2257-
if ([GPBUnknownFieldSet isFieldTag:tag]) {
2258-
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2259-
return [unknownFields mergeFieldFrom:tag input:input];
2260-
} else {
2261-
return NO;
2257+
GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
2258+
if (![unknownFields mergeFieldFrom:tag input:input]) {
2259+
[NSException raise:NSInternalInconsistencyException
2260+
format:@"Internal Error: Unable to parse unknown field %u", tag];
22622261
}
22632262
}
22642263

@@ -2465,7 +2464,12 @@ static void MergeRepeatedNotPackedFieldFromCodedInputStream(
24652464
}
24662465

24672466
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
2468-
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
2467+
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
2468+
endingTag:(uint32_t)endingTag {
2469+
#if defined(DEBUG) && DEBUG
2470+
NSAssert(endingTag == 0 || GPBWireFormatGetTagWireType(endingTag) == GPBWireFormatEndGroup,
2471+
@"endingTag should have been an endGroup tag");
2472+
#endif // DEBUG
24692473
GPBDescriptor *descriptor = [self descriptor];
24702474
GPBCodedInputStreamState *state = &input->state_;
24712475
uint32_t tag = 0;
@@ -2475,8 +2479,11 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
24752479
while (YES) {
24762480
BOOL merged = NO;
24772481
tag = GPBCodedInputStreamReadTag(state);
2478-
if (tag == 0) {
2479-
break; // Reached end.
2482+
if (tag == endingTag || tag == 0) {
2483+
// If we got to the end (tag zero), when we were expecting the end group, this will
2484+
// raise the error.
2485+
GPBCodedInputStreamCheckLastTagWas(state, endingTag);
2486+
return;
24802487
}
24812488
for (NSUInteger i = 0; i < numFields; ++i) {
24822489
if (startingIndex >= numFields) startingIndex = 0;
@@ -2514,46 +2521,37 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
25142521
}
25152522
} // for(i < numFields)
25162523

2517-
if (!merged && (tag != 0)) {
2518-
// Primitive, repeated types can be packed on unpacked on the wire, and
2519-
// are parsed either way. The above loop covered tag in the preferred
2520-
// for, so this need to check the alternate form.
2521-
for (NSUInteger i = 0; i < numFields; ++i) {
2522-
if (startingIndex >= numFields) startingIndex = 0;
2523-
GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2524-
if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
2525-
!GPBFieldDataTypeIsObject(fieldDescriptor) &&
2526-
(GPBFieldAlternateTag(fieldDescriptor) == tag)) {
2527-
BOOL alternateIsPacked = !fieldDescriptor.isPackable;
2528-
if (alternateIsPacked) {
2529-
MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input);
2530-
// Well formed protos will only have a repeated field that is
2531-
// packed once, advance the starting index to the next field.
2532-
startingIndex += 1;
2533-
} else {
2534-
MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input,
2535-
extensionRegistry);
2536-
}
2537-
merged = YES;
2538-
break;
2539-
} else {
2524+
if (merged) continue; // On to the next tag
2525+
2526+
// Primitive, repeated types can be packed or unpacked on the wire, and
2527+
// are parsed either way. The above loop covered tag in the preferred
2528+
// for, so this need to check the alternate form.
2529+
for (NSUInteger i = 0; i < numFields; ++i) {
2530+
if (startingIndex >= numFields) startingIndex = 0;
2531+
GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
2532+
if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) &&
2533+
!GPBFieldDataTypeIsObject(fieldDescriptor) &&
2534+
(GPBFieldAlternateTag(fieldDescriptor) == tag)) {
2535+
BOOL alternateIsPacked = !fieldDescriptor.isPackable;
2536+
if (alternateIsPacked) {
2537+
MergeRepeatedPackedFieldFromCodedInputStream(self, fieldDescriptor, input);
2538+
// Well formed protos will only have a repeated field that is
2539+
// packed once, advance the starting index to the next field.
25402540
startingIndex += 1;
2541+
} else {
2542+
MergeRepeatedNotPackedFieldFromCodedInputStream(self, fieldDescriptor, input,
2543+
extensionRegistry);
25412544
}
2545+
merged = YES;
2546+
break;
2547+
} else {
2548+
startingIndex += 1;
25422549
}
25432550
}
25442551

2545-
if (!merged) {
2546-
if (tag == 0) {
2547-
// zero signals EOF / limit reached
2548-
return;
2549-
} else {
2550-
if (![self parseUnknownField:input extensionRegistry:extensionRegistry tag:tag]) {
2551-
// it's an endgroup tag
2552-
return;
2553-
}
2554-
}
2555-
} // if(!merged)
2552+
if (merged) continue; // On to the next tag
25562553

2554+
[self parseUnknownField:input extensionRegistry:extensionRegistry tag:tag];
25572555
} // while(YES)
25582556
}
25592557

@@ -3554,8 +3552,7 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder {
35543552
if (data.length) {
35553553
GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
35563554
@try {
3557-
[self mergeFromCodedInputStream:input extensionRegistry:nil];
3558-
[input checkLastTagWas:0];
3555+
[self mergeFromCodedInputStream:input extensionRegistry:nil endingTag:0];
35593556
} @finally {
35603557
[input release];
35613558
}

objectivec/GPBMessage_PackagePrivate.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
4747
// Parses a message of this type from the input and merges it with this
4848
// message.
4949
//
50+
// `endingTag` should be zero if expected to consume to the end of input, but if
51+
// the input is supposed to be a Group, it should be the endgroup tag to look for.
52+
//
5053
// Warning: This does not verify that all required fields are present in
5154
// the input message.
52-
// Note: The caller should call
53-
// -[CodedInputStream checkLastTagWas:] after calling this to
54-
// verify that the last tag seen was the appropriate end-group tag,
55-
// or zero for EOF.
5655
// NOTE: This will throw if there is an error while parsing.
5756
- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
58-
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry;
57+
extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
58+
endingTag:(uint32_t)endingTag;
5959

6060
- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
6161

objectivec/GPBUnknownFieldSet.m

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -212,10 +212,6 @@ - (NSData *)data {
212212
return data;
213213
}
214214

215-
+ (BOOL)isFieldTag:(int32_t)tag {
216-
return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup;
217-
}
218-
219215
- (void)addField:(GPBUnknownField *)field {
220216
int32_t number = [field number];
221217
checkNumber(number);

objectivec/GPBUnknownFieldSet_PackagePrivate.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
@interface GPBUnknownFieldSet ()
1616

17-
+ (BOOL)isFieldTag:(int32_t)tag;
18-
1917
- (NSData *)data;
2018

2119
- (size_t)serializedSize;

0 commit comments

Comments
 (0)