1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 #import "GPBCodedInputStream_PackagePrivate.h" 32 33 #import "GPBDictionary_PackagePrivate.h" 34 #import "GPBMessage_PackagePrivate.h" 35 #import "GPBUnknownFieldSet_PackagePrivate.h" 36 #import "GPBUtilities_PackagePrivate.h" 37 #import "GPBWireFormat.h" 38 39 static const NSUInteger kDefaultRecursionLimit = 64; 40 41 static void CheckSize(GPBCodedInputStreamState *state, size_t size) { 42 size_t newSize = state->bufferPos + size; 43 if (newSize > state->bufferSize) { 44 [NSException raise:NSParseErrorException format:@""]; 45 } 46 if (newSize > state->currentLimit) { 47 // Fast forward to end of currentLimit; 48 state->bufferPos = state->currentLimit; 49 [NSException raise:NSParseErrorException format:@""]; 50 } 51 } 52 53 static int8_t ReadRawByte(GPBCodedInputStreamState *state) { 54 CheckSize(state, sizeof(int8_t)); 55 return ((int8_t *)state->bytes)[state->bufferPos++]; 56 } 57 58 static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { 59 CheckSize(state, sizeof(int32_t)); 60 int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); 61 state->bufferPos += sizeof(int32_t); 62 return value; 63 } 64 65 static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { 66 CheckSize(state, sizeof(int64_t)); 67 int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); 68 state->bufferPos += sizeof(int64_t); 69 return value; 70 } 71 72 static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { 73 int8_t tmp = ReadRawByte(state); 74 if (tmp >= 0) { 75 return tmp; 76 } 77 int32_t result = tmp & 0x7f; 78 if ((tmp = ReadRawByte(state)) >= 0) { 79 result |= tmp << 7; 80 } else { 81 result |= (tmp & 0x7f) << 7; 82 if ((tmp = ReadRawByte(state)) >= 0) { 83 result |= tmp << 14; 84 } else { 85 result |= (tmp & 0x7f) << 14; 86 if ((tmp = ReadRawByte(state)) >= 0) { 87 result |= tmp << 21; 88 } else { 89 result |= (tmp & 0x7f) << 21; 90 result |= (tmp = ReadRawByte(state)) << 28; 91 if (tmp < 0) { 92 // Discard upper 32 bits. 93 for (int i = 0; i < 5; i++) { 94 if (ReadRawByte(state) >= 0) { 95 return result; 96 } 97 } 98 [NSException raise:NSParseErrorException 99 format:@"Unable to read varint32"]; 100 } 101 } 102 } 103 } 104 return result; 105 } 106 107 static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { 108 int32_t shift = 0; 109 int64_t result = 0; 110 while (shift < 64) { 111 int8_t b = ReadRawByte(state); 112 result |= (int64_t)(b & 0x7F) << shift; 113 if ((b & 0x80) == 0) { 114 return result; 115 } 116 shift += 7; 117 } 118 [NSException raise:NSParseErrorException format:@"Unable to read varint64"]; 119 return 0; 120 } 121 122 static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { 123 CheckSize(state, size); 124 state->bufferPos += size; 125 } 126 127 double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) { 128 int64_t value = ReadRawLittleEndian64(state); 129 return GPBConvertInt64ToDouble(value); 130 } 131 132 float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) { 133 int32_t value = ReadRawLittleEndian32(state); 134 return GPBConvertInt32ToFloat(value); 135 } 136 137 uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) { 138 uint64_t value = ReadRawVarint64(state); 139 return value; 140 } 141 142 uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) { 143 uint32_t value = ReadRawVarint32(state); 144 return value; 145 } 146 147 int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) { 148 int64_t value = ReadRawVarint64(state); 149 return value; 150 } 151 152 int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) { 153 int32_t value = ReadRawVarint32(state); 154 return value; 155 } 156 157 uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) { 158 uint64_t value = ReadRawLittleEndian64(state); 159 return value; 160 } 161 162 uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) { 163 uint32_t value = ReadRawLittleEndian32(state); 164 return value; 165 } 166 167 int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) { 168 int32_t value = ReadRawVarint32(state); 169 return value; 170 } 171 172 int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) { 173 int32_t value = ReadRawLittleEndian32(state); 174 return value; 175 } 176 177 int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) { 178 int64_t value = ReadRawLittleEndian64(state); 179 return value; 180 } 181 182 int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) { 183 int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state)); 184 return value; 185 } 186 187 int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) { 188 int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state)); 189 return value; 190 } 191 192 BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) { 193 return ReadRawVarint32(state) != 0; 194 } 195 196 int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) { 197 if (GPBCodedInputStreamIsAtEnd(state)) { 198 state->lastTag = 0; 199 return 0; 200 } 201 202 state->lastTag = ReadRawVarint32(state); 203 if (state->lastTag == 0) { 204 // If we actually read zero, that's not a valid tag. 205 [NSException raise:NSParseErrorException 206 format:@"Invalid last tag %d", state->lastTag]; 207 } 208 return state->lastTag; 209 } 210 211 NSString *GPBCodedInputStreamReadRetainedString( 212 GPBCodedInputStreamState *state) { 213 int32_t size = ReadRawVarint32(state); 214 NSString *result; 215 if (size == 0) { 216 result = @""; 217 } else { 218 CheckSize(state, size); 219 result = [[NSString alloc] initWithBytes:&state->bytes[state->bufferPos] 220 length:size 221 encoding:NSUTF8StringEncoding]; 222 state->bufferPos += size; 223 if (!result) { 224 #ifdef DEBUG 225 // https://developers.google.com/protocol-buffers/docs/proto#scalar 226 NSLog(@"UTF-8 failure, is some field type 'string' when it should be " 227 @"'bytes'?"); 228 #endif 229 [NSException raise:NSParseErrorException 230 format:@"Invalid UTF-8 for a 'string'"]; 231 } 232 } 233 return result; 234 } 235 236 NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) { 237 int32_t size = ReadRawVarint32(state); 238 if (size < 0) return nil; 239 CheckSize(state, size); 240 NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos 241 length:size]; 242 state->bufferPos += size; 243 return result; 244 } 245 246 NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( 247 GPBCodedInputStreamState *state) { 248 int32_t size = ReadRawVarint32(state); 249 if (size < 0) return nil; 250 CheckSize(state, size); 251 // Cast is safe because freeWhenDone is NO. 252 NSData *result = [[NSData alloc] 253 initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos) 254 length:size 255 freeWhenDone:NO]; 256 state->bufferPos += size; 257 return result; 258 } 259 260 size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, 261 size_t byteLimit) { 262 byteLimit += state->bufferPos; 263 size_t oldLimit = state->currentLimit; 264 if (byteLimit > oldLimit) { 265 [NSException raise:NSInvalidArgumentException 266 format:@"byteLimit > oldLimit: %tu > %tu", byteLimit, oldLimit]; 267 } 268 state->currentLimit = byteLimit; 269 return oldLimit; 270 } 271 272 void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, 273 size_t oldLimit) { 274 state->currentLimit = oldLimit; 275 } 276 277 size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) { 278 return state->currentLimit - state->bufferPos; 279 } 280 281 BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) { 282 return (state->bufferPos == state->bufferSize) || 283 (state->bufferPos == state->currentLimit); 284 } 285 286 void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, 287 int32_t value) { 288 if (state->lastTag != value) { 289 [NSException raise:NSParseErrorException 290 format:@"Last tag: %d should be %d", state->lastTag, value]; 291 } 292 } 293 294 @implementation GPBCodedInputStream 295 296 + (instancetype)streamWithData:(NSData *)data { 297 return [[[self alloc] initWithData:data] autorelease]; 298 } 299 300 - (instancetype)initWithData:(NSData *)data { 301 if ((self = [super init])) { 302 #ifdef DEBUG 303 NSCAssert([self class] == [GPBCodedInputStream class], 304 @"Subclassing of GPBCodedInputStream is not allowed."); 305 #endif 306 buffer_ = [data retain]; 307 state_.bytes = (const uint8_t *)[data bytes]; 308 state_.bufferSize = [data length]; 309 state_.currentLimit = state_.bufferSize; 310 } 311 return self; 312 } 313 314 - (void)dealloc { 315 [buffer_ release]; 316 [super dealloc]; 317 } 318 319 - (int32_t)readTag { 320 return GPBCodedInputStreamReadTag(&state_); 321 } 322 323 - (void)checkLastTagWas:(int32_t)value { 324 GPBCodedInputStreamCheckLastTagWas(&state_, value); 325 } 326 327 - (BOOL)skipField:(int32_t)tag { 328 switch (GPBWireFormatGetTagWireType(tag)) { 329 case GPBWireFormatVarint: 330 GPBCodedInputStreamReadInt32(&state_); 331 return YES; 332 case GPBWireFormatFixed64: 333 SkipRawData(&state_, sizeof(int64_t)); 334 return YES; 335 case GPBWireFormatLengthDelimited: 336 SkipRawData(&state_, ReadRawVarint32(&state_)); 337 return YES; 338 case GPBWireFormatStartGroup: 339 [self skipMessage]; 340 GPBCodedInputStreamCheckLastTagWas( 341 &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag), 342 GPBWireFormatEndGroup)); 343 return YES; 344 case GPBWireFormatEndGroup: 345 return NO; 346 case GPBWireFormatFixed32: 347 SkipRawData(&state_, sizeof(int32_t)); 348 return YES; 349 } 350 [NSException raise:NSParseErrorException format:@"Invalid tag %d", tag]; 351 return NO; 352 } 353 354 - (void)skipMessage { 355 while (YES) { 356 int32_t tag = GPBCodedInputStreamReadTag(&state_); 357 if (tag == 0 || ![self skipField:tag]) { 358 return; 359 } 360 } 361 } 362 363 - (BOOL)isAtEnd { 364 return GPBCodedInputStreamIsAtEnd(&state_); 365 } 366 367 - (size_t)position { 368 return state_.bufferPos; 369 } 370 371 - (double)readDouble { 372 return GPBCodedInputStreamReadDouble(&state_); 373 } 374 375 - (float)readFloat { 376 return GPBCodedInputStreamReadFloat(&state_); 377 } 378 379 - (uint64_t)readUInt64 { 380 return GPBCodedInputStreamReadUInt64(&state_); 381 } 382 383 - (int64_t)readInt64 { 384 return GPBCodedInputStreamReadInt64(&state_); 385 } 386 387 - (int32_t)readInt32 { 388 return GPBCodedInputStreamReadInt32(&state_); 389 } 390 391 - (uint64_t)readFixed64 { 392 return GPBCodedInputStreamReadFixed64(&state_); 393 } 394 395 - (uint32_t)readFixed32 { 396 return GPBCodedInputStreamReadFixed32(&state_); 397 } 398 399 - (BOOL)readBool { 400 return GPBCodedInputStreamReadBool(&state_); 401 } 402 403 - (NSString *)readString { 404 return [GPBCodedInputStreamReadRetainedString(&state_) autorelease]; 405 } 406 407 - (void)readGroup:(int32_t)fieldNumber 408 message:(GPBMessage *)message 409 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 410 if (state_.recursionDepth >= kDefaultRecursionLimit) { 411 [NSException raise:NSParseErrorException 412 format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, 413 kDefaultRecursionLimit]; 414 } 415 ++state_.recursionDepth; 416 [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; 417 GPBCodedInputStreamCheckLastTagWas( 418 &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); 419 --state_.recursionDepth; 420 } 421 422 - (void)readUnknownGroup:(int32_t)fieldNumber 423 message:(GPBUnknownFieldSet *)message { 424 if (state_.recursionDepth >= kDefaultRecursionLimit) { 425 [NSException raise:NSParseErrorException 426 format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, 427 kDefaultRecursionLimit]; 428 } 429 ++state_.recursionDepth; 430 [message mergeFromCodedInputStream:self]; 431 GPBCodedInputStreamCheckLastTagWas( 432 &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup)); 433 --state_.recursionDepth; 434 } 435 436 - (void)readMessage:(GPBMessage *)message 437 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { 438 int32_t length = ReadRawVarint32(&state_); 439 if (state_.recursionDepth >= kDefaultRecursionLimit) { 440 [NSException raise:NSParseErrorException 441 format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, 442 kDefaultRecursionLimit]; 443 } 444 size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); 445 ++state_.recursionDepth; 446 [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry]; 447 GPBCodedInputStreamCheckLastTagWas(&state_, 0); 448 --state_.recursionDepth; 449 GPBCodedInputStreamPopLimit(&state_, oldLimit); 450 } 451 452 - (void)readMapEntry:(id)mapDictionary 453 extensionRegistry:(GPBExtensionRegistry *)extensionRegistry 454 field:(GPBFieldDescriptor *)field 455 parentMessage:(GPBMessage *)parentMessage { 456 int32_t length = ReadRawVarint32(&state_); 457 if (state_.recursionDepth >= kDefaultRecursionLimit) { 458 [NSException raise:NSParseErrorException 459 format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth, 460 kDefaultRecursionLimit]; 461 } 462 size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length); 463 ++state_.recursionDepth; 464 GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field, 465 parentMessage); 466 GPBCodedInputStreamCheckLastTagWas(&state_, 0); 467 --state_.recursionDepth; 468 GPBCodedInputStreamPopLimit(&state_, oldLimit); 469 } 470 471 - (NSData *)readBytes { 472 return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease]; 473 } 474 475 - (uint32_t)readUInt32 { 476 return GPBCodedInputStreamReadUInt32(&state_); 477 } 478 479 - (int32_t)readEnum { 480 return GPBCodedInputStreamReadEnum(&state_); 481 } 482 483 - (int32_t)readSFixed32 { 484 return GPBCodedInputStreamReadSFixed32(&state_); 485 } 486 487 - (int64_t)readSFixed64 { 488 return GPBCodedInputStreamReadSFixed64(&state_); 489 } 490 491 - (int32_t)readSInt32 { 492 return GPBCodedInputStreamReadSInt32(&state_); 493 } 494 495 - (int64_t)readSInt64 { 496 return GPBCodedInputStreamReadSInt64(&state_); 497 } 498 499 @end 500