@@ -742,16 +742,12 @@ static void DecodeSingleValueFromInputStream(GPBExtensionDescriptor *extension,
742
742
message: targetMessage
743
743
extensionRegistry: extensionRegistry];
744
744
} else {
745
- // description->dataType == GPBDataTypeMessage
746
- if (GPBExtensionIsWireFormat (description)) {
747
- // For MessageSet fields the message length will have already been
748
- // read.
749
- [targetMessage mergeFromCodedInputStream: input
750
- extensionRegistry: extensionRegistry
751
- endingTag: 0 ];
752
- } else {
753
- [input readMessage: targetMessage extensionRegistry: extensionRegistry];
754
- }
745
+ // description->dataType == GPBDataTypeMessage
746
+ #if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
747
+ NSCAssert (!GPBExtensionIsWireFormat(description),
748
+ @"Internal error: got a MessageSet extension when not expected.");
749
+ #endif
750
+ [input readMessage: targetMessage extensionRegistry: extensionRegistry];
755
751
}
756
752
// Nothing to add below since the caller provided the message (and added it).
757
753
nsValue = nil ;
@@ -2183,81 +2179,85 @@ - (void)parseMessageSet:(GPBCodedInputStream *)input
2183
2179
extensionRegistry:(id <GPBExtensionRegistry>)extensionRegistry {
2184
2180
uint32_t typeId = 0 ;
2185
2181
NSData *rawBytes = nil ;
2186
- GPBExtensionDescriptor *extension = nil ;
2187
2182
GPBCodedInputStreamState *state = &input->state_ ;
2183
+ BOOL gotType = NO ;
2184
+ BOOL gotBytes = NO ;
2188
2185
while (true ) {
2189
2186
uint32_t tag = GPBCodedInputStreamReadTag (state);
2190
- if (tag == 0 ) {
2187
+ if (tag == GPBWireFormatMessageSetItemEndTag || tag == 0 ) {
2191
2188
break ;
2192
2189
}
2193
2190
2194
2191
if (tag == GPBWireFormatMessageSetTypeIdTag) {
2195
- typeId = GPBCodedInputStreamReadUInt32 (state);
2196
- if (typeId != 0 ) {
2197
- extension = [extensionRegistry extensionForDescriptor: [self descriptor ] fieldNumber: typeId];
2192
+ uint32_t tmp = GPBCodedInputStreamReadUInt32 (state);
2193
+ // Spec says only use the first value.
2194
+ if (!gotType) {
2195
+ gotType = YES ;
2196
+ typeId = tmp;
2198
2197
}
2199
2198
} else if (tag == GPBWireFormatMessageSetMessageTag) {
2200
- rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy (state) autorelease ];
2199
+ if (gotBytes) {
2200
+ // Skip over the payload instead of collecting it.
2201
+ [input skipField: tag];
2202
+ } else {
2203
+ rawBytes = [GPBCodedInputStreamReadRetainedBytesNoCopy (state) autorelease ];
2204
+ gotBytes = YES ;
2205
+ }
2201
2206
} else {
2207
+ // Don't capture unknowns within the message set impl group.
2202
2208
if (![input skipField: tag]) {
2203
2209
break ;
2204
2210
}
2205
2211
}
2206
2212
}
2207
2213
2208
- [input checkLastTagWas: GPBWireFormatMessageSetItemEndTag];
2214
+ // If we get here because of end of input (tag zero) or the wrong end tag (within the skipField:),
2215
+ // this will error.
2216
+ GPBCodedInputStreamCheckLastTagWas (state, GPBWireFormatMessageSetItemEndTag);
2209
2217
2210
- if (rawBytes != nil && typeId != 0 ) {
2211
- if (extension != nil ) {
2212
- GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc ] initWithData: rawBytes];
2213
- @try {
2214
- ExtensionMergeFromInputStream (extension, extension.packable , newInput, extensionRegistry,
2215
- self);
2216
- } @finally {
2217
- [newInput release ];
2218
- }
2219
- } else {
2220
- GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields (self);
2221
- // rawBytes was created via a NoCopy, so it can be reusing a
2222
- // subrange of another NSData that might go out of scope as things
2223
- // unwind, so a copy is needed to ensure what is saved in the
2224
- // unknown fields stays valid.
2225
- NSData *cloned = [NSData dataWithData: rawBytes];
2226
- [unknownFields mergeMessageSetMessage: typeId data: cloned];
2227
- }
2218
+ if (!gotType || !gotBytes) {
2219
+ // upb_Decoder_DecodeMessageSetItem does't keep this partial as an unknown field, it just drops
2220
+ // it, so do the same thing.
2221
+ return ;
2228
2222
}
2229
- }
2230
2223
2231
- - (void )parseUnknownField:(GPBCodedInputStream *)input
2232
- extensionRegistry:(id <GPBExtensionRegistry>)extensionRegistry
2233
- tag:(uint32_t )tag {
2234
- int32_t fieldNumber = GPBWireFormatGetTagFieldNumber (tag);
2235
- GPBDescriptor *descriptor = [self descriptor ];
2236
- GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor: descriptor
2237
- fieldNumber: fieldNumber];
2238
- if (extension == nil ) {
2239
- if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
2240
- [self parseMessageSet: input extensionRegistry: extensionRegistry];
2241
- return ;
2224
+ GPBExtensionDescriptor *extension = [extensionRegistry extensionForDescriptor: [self descriptor ]
2225
+ fieldNumber: typeId];
2226
+ if (extension) {
2227
+ #if defined(DEBUG) && DEBUG && !defined(NS_BLOCK_ASSERTIONS)
2228
+ NSAssert (extension.dataType == GPBDataTypeMessage,
2229
+ @" Internal Error: MessageSet extension must be a message field." );
2230
+ NSAssert (GPBExtensionIsWireFormat(extension->description_),
2231
+ @"Internal Error: MessageSet extension must have message_set_wire_format set.");
2232
+ NSAssert (!GPBExtensionIsRepeated(extension->description_),
2233
+ @"Internal Error: MessageSet extension can't be repeated.");
2234
+ #endif
2235
+ // Look up the existing one to merge to or create a new one.
2236
+ GPBMessage *targetMessage = [self getExistingExtension: extension];
2237
+ if (!targetMessage) {
2238
+ GPBDescriptor *descriptor = [extension.msgClass descriptor ];
2239
+ targetMessage = [[descriptor.messageClass alloc ] init ];
2240
+ [self setExtension: extension value: targetMessage];
2241
+ [targetMessage release ];
2242
+ }
2243
+ GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc ] initWithData: rawBytes];
2244
+ @try {
2245
+ [targetMessage mergeFromCodedInputStream: newInput
2246
+ extensionRegistry: extensionRegistry
2247
+ endingTag: 0 ];
2248
+ } @finally {
2249
+ [newInput release ];
2242
2250
}
2243
2251
} else {
2244
- GPBWireFormat wireType = GPBWireFormatGetTagWireType (tag);
2245
- if (extension.wireType == wireType) {
2246
- ExtensionMergeFromInputStream (extension, extension.packable , input, extensionRegistry, self);
2247
- return ;
2248
- }
2249
- // Primitive, repeated types can be packed on unpacked on the wire, and are
2250
- // parsed either way.
2251
- if ([extension isRepeated ] && !GPBDataTypeIsObject (extension->description_ ->dataType ) &&
2252
- (extension.alternateWireType == wireType)) {
2253
- ExtensionMergeFromInputStream (extension, !extension.packable , input, extensionRegistry, self);
2254
- return ;
2255
- }
2256
- }
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];
2252
+ // The extension isn't in the registry, but it was well formed, so the whole group structure
2253
+ // get preserved as an unknown field.
2254
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields (self);
2255
+ // rawBytes was created via a NoCopy, so it can be reusing a
2256
+ // subrange of another NSData that might go out of scope as things
2257
+ // unwind, so a copy is needed to ensure what is saved in the
2258
+ // unknown fields stays valid.
2259
+ NSData *cloned = [NSData dataWithData: rawBytes];
2260
+ [unknownFields mergeMessageSetMessage: typeId data: cloned];
2261
2261
}
2262
2262
}
2263
2263
@@ -2475,6 +2475,7 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
2475
2475
uint32_t tag = 0 ;
2476
2476
NSUInteger startingIndex = 0 ;
2477
2477
NSArray *fields = descriptor->fields_ ;
2478
+ BOOL isMessageSetWireFormat = descriptor.isWireFormat ;
2478
2479
NSUInteger numFields = fields.count ;
2479
2480
while (YES ) {
2480
2481
BOOL merged = NO ;
@@ -2551,7 +2552,40 @@ - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
2551
2552
2552
2553
if (merged) continue ; // On to the next tag
2553
2554
2554
- [self parseUnknownField: input extensionRegistry: extensionRegistry tag: tag];
2555
+ if (isMessageSetWireFormat) {
2556
+ if (GPBWireFormatMessageSetItemTag == tag) {
2557
+ [self parseMessageSet: input extensionRegistry: extensionRegistry];
2558
+ continue ; // On to the next tag
2559
+ }
2560
+ } else {
2561
+ // ObjC Runtime currently doesn't track if a message supported extensions, so the check is
2562
+ // always done.
2563
+ GPBExtensionDescriptor *extension =
2564
+ [extensionRegistry extensionForDescriptor: descriptor
2565
+ fieldNumber: GPBWireFormatGetTagFieldNumber (tag)];
2566
+ if (extension) {
2567
+ GPBWireFormat wireType = GPBWireFormatGetTagWireType (tag);
2568
+ if (extension.wireType == wireType) {
2569
+ ExtensionMergeFromInputStream (extension, extension.packable , input, extensionRegistry,
2570
+ self);
2571
+ continue ; // On to the next tag
2572
+ }
2573
+ // Primitive, repeated types can be packed on unpacked on the wire, and are
2574
+ // parsed either way.
2575
+ if ([extension isRepeated ] && !GPBDataTypeIsObject (extension->description_ ->dataType ) &&
2576
+ (extension.alternateWireType == wireType)) {
2577
+ ExtensionMergeFromInputStream (extension, !extension.packable , input, extensionRegistry,
2578
+ self);
2579
+ continue ; // On to the next tag
2580
+ }
2581
+ }
2582
+ }
2583
+
2584
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields (self);
2585
+ if (![unknownFields mergeFieldFrom: tag input: input]) {
2586
+ [NSException raise :NSInternalInconsistencyException
2587
+ format: @" Internal Error: Unable to parse unknown field %u " , tag];
2588
+ }
2555
2589
} // while(YES)
2556
2590
}
2557
2591
0 commit comments