1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 package com.google.protobuf; 9 10 import static com.google.protobuf.MessageSchema.getMutableUnknownFields; 11 12 import com.google.protobuf.GeneratedMessageLite.ExtensionDescriptor; 13 import com.google.protobuf.Internal.ProtobufList; 14 import java.io.IOException; 15 16 /** 17 * Helper functions to decode protobuf wire format from a byte array. 18 * 19 * <p>Note that these functions don't do boundary check on the byte array but instead rely on Java 20 * VM to check it. That means parsing routines utilizing these functions must catch 21 * IndexOutOfBoundsException and convert it to protobuf's InvalidProtocolBufferException when 22 * crossing protobuf public API boundaries. 23 */ 24 @CheckReturnValue 25 final class ArrayDecoders { 26 static final int DEFAULT_RECURSION_LIMIT = 100; 27 28 @SuppressWarnings("NonFinalStaticField") 29 private static volatile int recursionLimit = DEFAULT_RECURSION_LIMIT; 30 ArrayDecoders()31 private ArrayDecoders() {} 32 33 /** 34 * A helper used to return multiple values in a Java function. Java doesn't natively support 35 * returning multiple values in a function. Creating a new Object to hold the return values will 36 * be too expensive. Instead, we pass a Registers instance to functions that want to return 37 * multiple values and let the function set the return value in this Registers instance instead. 38 */ 39 static final class Registers { 40 public int int1; 41 public long long1; 42 public Object object1; 43 public final ExtensionRegistryLite extensionRegistry; 44 public int recursionDepth; 45 Registers()46 Registers() { 47 this.extensionRegistry = ExtensionRegistryLite.getEmptyRegistry(); 48 } 49 Registers(ExtensionRegistryLite extensionRegistry)50 Registers(ExtensionRegistryLite extensionRegistry) { 51 if (extensionRegistry == null) { 52 throw new NullPointerException(); 53 } 54 this.extensionRegistry = extensionRegistry; 55 } 56 } 57 58 /** 59 * Decodes a varint. Returns the position after the varint. The decoded varint is stored in 60 * registers.int1. 61 */ decodeVarint32(byte[] data, int position, Registers registers)62 static int decodeVarint32(byte[] data, int position, Registers registers) { 63 int value = data[position++]; 64 if (value >= 0) { 65 registers.int1 = value; 66 return position; 67 } 68 return decodeVarint32(value, data, position, registers); 69 } 70 71 /** Like decodeVarint32 except that the first byte is already read. */ decodeVarint32(int firstByte, byte[] data, int position, Registers registers)72 static int decodeVarint32(int firstByte, byte[] data, int position, Registers registers) { 73 int value = firstByte & 0x7F; 74 final byte b2 = data[position++]; 75 if (b2 >= 0) { 76 registers.int1 = value | ((int) b2 << 7); 77 return position; 78 } 79 value |= (b2 & 0x7F) << 7; 80 81 final byte b3 = data[position++]; 82 if (b3 >= 0) { 83 registers.int1 = value | ((int) b3 << 14); 84 return position; 85 } 86 value |= (b3 & 0x7F) << 14; 87 88 final byte b4 = data[position++]; 89 if (b4 >= 0) { 90 registers.int1 = value | ((int) b4 << 21); 91 return position; 92 } 93 value |= (b4 & 0x7F) << 21; 94 95 final byte b5 = data[position++]; 96 if (b5 >= 0) { 97 registers.int1 = value | ((int) b5 << 28); 98 return position; 99 } 100 value |= (b5 & 0x7F) << 28; 101 102 while (data[position++] < 0) {} 103 104 registers.int1 = value; 105 return position; 106 } 107 108 /** 109 * Decodes a varint. Returns the position after the varint. The decoded varint is stored in 110 * registers.long1. 111 */ decodeVarint64(byte[] data, int position, Registers registers)112 static int decodeVarint64(byte[] data, int position, Registers registers) { 113 long value = data[position++]; 114 if (value >= 0) { 115 registers.long1 = value; 116 return position; 117 } else { 118 return decodeVarint64(value, data, position, registers); 119 } 120 } 121 122 /** Like decodeVarint64 except that the first byte is already read. */ decodeVarint64(long firstByte, byte[] data, int position, Registers registers)123 static int decodeVarint64(long firstByte, byte[] data, int position, Registers registers) { 124 long value = firstByte & 0x7F; 125 byte next = data[position++]; 126 int shift = 7; 127 value |= (long) (next & 0x7F) << 7; 128 while (next < 0) { 129 next = data[position++]; 130 shift += 7; 131 value |= (long) (next & 0x7F) << shift; 132 } 133 registers.long1 = value; 134 return position; 135 } 136 137 /** Decodes and returns a fixed32 value. */ decodeFixed32(byte[] data, int position)138 static int decodeFixed32(byte[] data, int position) { 139 return (data[position] & 0xff) 140 | ((data[position + 1] & 0xff) << 8) 141 | ((data[position + 2] & 0xff) << 16) 142 | ((data[position + 3] & 0xff) << 24); 143 } 144 145 /** Decodes and returns a fixed64 value. */ decodeFixed64(byte[] data, int position)146 static long decodeFixed64(byte[] data, int position) { 147 return (data[position] & 0xffL) 148 | ((data[position + 1] & 0xffL) << 8) 149 | ((data[position + 2] & 0xffL) << 16) 150 | ((data[position + 3] & 0xffL) << 24) 151 | ((data[position + 4] & 0xffL) << 32) 152 | ((data[position + 5] & 0xffL) << 40) 153 | ((data[position + 6] & 0xffL) << 48) 154 | ((data[position + 7] & 0xffL) << 56); 155 } 156 157 /** Decodes and returns a double value. */ decodeDouble(byte[] data, int position)158 static double decodeDouble(byte[] data, int position) { 159 return Double.longBitsToDouble(decodeFixed64(data, position)); 160 } 161 162 /** Decodes and returns a float value. */ decodeFloat(byte[] data, int position)163 static float decodeFloat(byte[] data, int position) { 164 return Float.intBitsToFloat(decodeFixed32(data, position)); 165 } 166 167 /** Decodes a string value. */ decodeString(byte[] data, int position, Registers registers)168 static int decodeString(byte[] data, int position, Registers registers) 169 throws InvalidProtocolBufferException { 170 position = decodeVarint32(data, position, registers); 171 final int length = registers.int1; 172 if (length < 0) { 173 throw InvalidProtocolBufferException.negativeSize(); 174 } else if (length == 0) { 175 registers.object1 = ""; 176 return position; 177 } else { 178 registers.object1 = new String(data, position, length, Internal.UTF_8); 179 return position + length; 180 } 181 } 182 183 /** Decodes a string value with utf8 check. */ decodeStringRequireUtf8(byte[] data, int position, Registers registers)184 static int decodeStringRequireUtf8(byte[] data, int position, Registers registers) 185 throws InvalidProtocolBufferException { 186 position = decodeVarint32(data, position, registers); 187 final int length = registers.int1; 188 if (length < 0) { 189 throw InvalidProtocolBufferException.negativeSize(); 190 } else if (length == 0) { 191 registers.object1 = ""; 192 return position; 193 } else { 194 registers.object1 = Utf8.decodeUtf8(data, position, length); 195 return position + length; 196 } 197 } 198 199 /** Decodes a bytes value. */ decodeBytes(byte[] data, int position, Registers registers)200 static int decodeBytes(byte[] data, int position, Registers registers) 201 throws InvalidProtocolBufferException { 202 position = decodeVarint32(data, position, registers); 203 final int length = registers.int1; 204 if (length < 0) { 205 throw InvalidProtocolBufferException.negativeSize(); 206 } else if (length > data.length - position) { 207 throw InvalidProtocolBufferException.truncatedMessage(); 208 } else if (length == 0) { 209 registers.object1 = ByteString.EMPTY; 210 return position; 211 } else { 212 registers.object1 = ByteString.copyFrom(data, position, length); 213 return position + length; 214 } 215 } 216 217 /** Decodes a message value. */ 218 @SuppressWarnings({"unchecked", "rawtypes"}) decodeMessageField( Schema schema, byte[] data, int position, int limit, Registers registers)219 static int decodeMessageField( 220 Schema schema, byte[] data, int position, int limit, Registers registers) throws IOException { 221 Object msg = schema.newInstance(); 222 int offset = mergeMessageField(msg, schema, data, position, limit, registers); 223 schema.makeImmutable(msg); 224 registers.object1 = msg; 225 return offset; 226 } 227 228 /** Decodes a group value. */ 229 @SuppressWarnings({"unchecked", "rawtypes"}) decodeGroupField( Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)230 static int decodeGroupField( 231 Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers) 232 throws IOException { 233 Object msg = schema.newInstance(); 234 int offset = mergeGroupField(msg, schema, data, position, limit, endGroup, registers); 235 schema.makeImmutable(msg); 236 registers.object1 = msg; 237 return offset; 238 } 239 240 @SuppressWarnings({"unchecked", "rawtypes"}) mergeMessageField( Object msg, Schema schema, byte[] data, int position, int limit, Registers registers)241 static int mergeMessageField( 242 Object msg, Schema schema, byte[] data, int position, int limit, Registers registers) 243 throws IOException { 244 int length = data[position++]; 245 if (length < 0) { 246 position = decodeVarint32(length, data, position, registers); 247 length = registers.int1; 248 } 249 if (length < 0 || length > limit - position) { 250 throw InvalidProtocolBufferException.truncatedMessage(); 251 } 252 registers.recursionDepth++; 253 checkRecursionLimit(registers.recursionDepth); 254 schema.mergeFrom(msg, data, position, position + length, registers); 255 registers.recursionDepth--; 256 registers.object1 = msg; 257 return position + length; 258 } 259 260 @SuppressWarnings({"unchecked", "rawtypes"}) mergeGroupField( Object msg, Schema schema, byte[] data, int position, int limit, int endGroup, Registers registers)261 static int mergeGroupField( 262 Object msg, 263 Schema schema, 264 byte[] data, 265 int position, 266 int limit, 267 int endGroup, 268 Registers registers) 269 throws IOException { 270 // A group field must has a MessageSchema (the only other subclass of Schema is MessageSetSchema 271 // and it can't be used in group fields). 272 final MessageSchema messageSchema = (MessageSchema) schema; 273 registers.recursionDepth++; 274 checkRecursionLimit(registers.recursionDepth); 275 final int endPosition = 276 messageSchema.parseMessage(msg, data, position, limit, endGroup, registers); 277 registers.recursionDepth--; 278 registers.object1 = msg; 279 return endPosition; 280 } 281 282 /** Decodes a repeated 32-bit varint field. Returns the position after all read values. */ decodeVarint32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)283 static int decodeVarint32List( 284 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 285 final IntArrayList output = (IntArrayList) list; 286 position = decodeVarint32(data, position, registers); 287 output.addInt(registers.int1); 288 while (position < limit) { 289 int nextPosition = decodeVarint32(data, position, registers); 290 if (tag != registers.int1) { 291 break; 292 } 293 position = decodeVarint32(data, nextPosition, registers); 294 output.addInt(registers.int1); 295 } 296 return position; 297 } 298 299 /** Decodes a repeated 64-bit varint field. Returns the position after all read values. */ decodeVarint64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)300 static int decodeVarint64List( 301 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 302 final LongArrayList output = (LongArrayList) list; 303 position = decodeVarint64(data, position, registers); 304 output.addLong(registers.long1); 305 while (position < limit) { 306 int nextPosition = decodeVarint32(data, position, registers); 307 if (tag != registers.int1) { 308 break; 309 } 310 position = decodeVarint64(data, nextPosition, registers); 311 output.addLong(registers.long1); 312 } 313 return position; 314 } 315 316 /** Decodes a repeated fixed32 field. Returns the position after all read values. */ decodeFixed32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)317 static int decodeFixed32List( 318 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 319 final IntArrayList output = (IntArrayList) list; 320 output.addInt(decodeFixed32(data, position)); 321 position += 4; 322 while (position < limit) { 323 int nextPosition = decodeVarint32(data, position, registers); 324 if (tag != registers.int1) { 325 break; 326 } 327 output.addInt(decodeFixed32(data, nextPosition)); 328 position = nextPosition + 4; 329 } 330 return position; 331 } 332 333 /** Decodes a repeated fixed64 field. Returns the position after all read values. */ decodeFixed64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)334 static int decodeFixed64List( 335 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 336 final LongArrayList output = (LongArrayList) list; 337 output.addLong(decodeFixed64(data, position)); 338 position += 8; 339 while (position < limit) { 340 int nextPosition = decodeVarint32(data, position, registers); 341 if (tag != registers.int1) { 342 break; 343 } 344 output.addLong(decodeFixed64(data, nextPosition)); 345 position = nextPosition + 8; 346 } 347 return position; 348 } 349 350 /** Decodes a repeated float field. Returns the position after all read values. */ decodeFloatList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)351 static int decodeFloatList( 352 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 353 final FloatArrayList output = (FloatArrayList) list; 354 output.addFloat(decodeFloat(data, position)); 355 position += 4; 356 while (position < limit) { 357 int nextPosition = decodeVarint32(data, position, registers); 358 if (tag != registers.int1) { 359 break; 360 } 361 output.addFloat(decodeFloat(data, nextPosition)); 362 position = nextPosition + 4; 363 } 364 return position; 365 } 366 367 /** Decodes a repeated double field. Returns the position after all read values. */ decodeDoubleList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)368 static int decodeDoubleList( 369 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 370 final DoubleArrayList output = (DoubleArrayList) list; 371 output.addDouble(decodeDouble(data, position)); 372 position += 8; 373 while (position < limit) { 374 int nextPosition = decodeVarint32(data, position, registers); 375 if (tag != registers.int1) { 376 break; 377 } 378 output.addDouble(decodeDouble(data, nextPosition)); 379 position = nextPosition + 8; 380 } 381 return position; 382 } 383 384 /** Decodes a repeated boolean field. Returns the position after all read values. */ decodeBoolList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)385 static int decodeBoolList( 386 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 387 final BooleanArrayList output = (BooleanArrayList) list; 388 position = decodeVarint64(data, position, registers); 389 output.addBoolean(registers.long1 != 0); 390 while (position < limit) { 391 int nextPosition = decodeVarint32(data, position, registers); 392 if (tag != registers.int1) { 393 break; 394 } 395 position = decodeVarint64(data, nextPosition, registers); 396 output.addBoolean(registers.long1 != 0); 397 } 398 return position; 399 } 400 401 /** Decodes a repeated sint32 field. Returns the position after all read values. */ decodeSInt32List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)402 static int decodeSInt32List( 403 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 404 final IntArrayList output = (IntArrayList) list; 405 position = decodeVarint32(data, position, registers); 406 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 407 while (position < limit) { 408 int nextPosition = decodeVarint32(data, position, registers); 409 if (tag != registers.int1) { 410 break; 411 } 412 position = decodeVarint32(data, nextPosition, registers); 413 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 414 } 415 return position; 416 } 417 418 /** Decodes a repeated sint64 field. Returns the position after all read values. */ decodeSInt64List( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)419 static int decodeSInt64List( 420 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) { 421 final LongArrayList output = (LongArrayList) list; 422 position = decodeVarint64(data, position, registers); 423 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 424 while (position < limit) { 425 int nextPosition = decodeVarint32(data, position, registers); 426 if (tag != registers.int1) { 427 break; 428 } 429 position = decodeVarint64(data, nextPosition, registers); 430 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 431 } 432 return position; 433 } 434 435 /** Decodes a packed 32-bit varint field. Returns the position after all read values. */ decodePackedVarint32List( byte[] data, int position, ProtobufList<?> list, Registers registers)436 static int decodePackedVarint32List( 437 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 438 final IntArrayList output = (IntArrayList) list; 439 position = decodeVarint32(data, position, registers); 440 final int fieldLimit = position + registers.int1; 441 while (position < fieldLimit) { 442 position = decodeVarint32(data, position, registers); 443 output.addInt(registers.int1); 444 } 445 if (position != fieldLimit) { 446 throw InvalidProtocolBufferException.truncatedMessage(); 447 } 448 return position; 449 } 450 451 /** Decodes a packed 64-bit varint field. Returns the position after all read values. */ decodePackedVarint64List( byte[] data, int position, ProtobufList<?> list, Registers registers)452 static int decodePackedVarint64List( 453 byte[] data, int position, ProtobufList<?> list, Registers registers) throws IOException { 454 final LongArrayList output = (LongArrayList) list; 455 position = decodeVarint32(data, position, registers); 456 final int fieldLimit = position + registers.int1; 457 while (position < fieldLimit) { 458 position = decodeVarint64(data, position, registers); 459 output.addLong(registers.long1); 460 } 461 if (position != fieldLimit) { 462 throw InvalidProtocolBufferException.truncatedMessage(); 463 } 464 return position; 465 } 466 467 /** Decodes a packed fixed32 field. Returns the position after all read values. */ decodePackedFixed32List( byte[] data, int position, ProtobufList<?> list, Registers registers)468 static int decodePackedFixed32List( 469 byte[] data, int position, ProtobufList<?> list, Registers registers) 470 throws InvalidProtocolBufferException { 471 final IntArrayList output = (IntArrayList) list; 472 position = decodeVarint32(data, position, registers); 473 final int packedDataByteSize = registers.int1; 474 final int fieldLimit = position + packedDataByteSize; 475 if (fieldLimit > data.length) { 476 throw InvalidProtocolBufferException.truncatedMessage(); 477 } 478 output.ensureCapacity(output.size() + packedDataByteSize / 4); 479 while (position < fieldLimit) { 480 output.addInt(decodeFixed32(data, position)); 481 position += 4; 482 } 483 if (position != fieldLimit) { 484 throw InvalidProtocolBufferException.truncatedMessage(); 485 } 486 return position; 487 } 488 489 /** Decodes a packed fixed64 field. Returns the position after all read values. */ decodePackedFixed64List( byte[] data, int position, ProtobufList<?> list, Registers registers)490 static int decodePackedFixed64List( 491 byte[] data, int position, ProtobufList<?> list, Registers registers) 492 throws InvalidProtocolBufferException { 493 final LongArrayList output = (LongArrayList) list; 494 position = decodeVarint32(data, position, registers); 495 final int packedDataByteSize = registers.int1; 496 final int fieldLimit = position + packedDataByteSize; 497 if (fieldLimit > data.length) { 498 throw InvalidProtocolBufferException.truncatedMessage(); 499 } 500 output.ensureCapacity(output.size() + packedDataByteSize / 8); 501 while (position < fieldLimit) { 502 output.addLong(decodeFixed64(data, position)); 503 position += 8; 504 } 505 if (position != fieldLimit) { 506 throw InvalidProtocolBufferException.truncatedMessage(); 507 } 508 return position; 509 } 510 511 /** Decodes a packed float field. Returns the position after all read values. */ decodePackedFloatList( byte[] data, int position, ProtobufList<?> list, Registers registers)512 static int decodePackedFloatList( 513 byte[] data, int position, ProtobufList<?> list, Registers registers) 514 throws InvalidProtocolBufferException { 515 final FloatArrayList output = (FloatArrayList) list; 516 position = decodeVarint32(data, position, registers); 517 final int packedDataByteSize = registers.int1; 518 final int fieldLimit = position + packedDataByteSize; 519 if (fieldLimit > data.length) { 520 throw InvalidProtocolBufferException.truncatedMessage(); 521 } 522 output.ensureCapacity(output.size() + packedDataByteSize / 4); 523 while (position < fieldLimit) { 524 output.addFloat(decodeFloat(data, position)); 525 position += 4; 526 } 527 if (position != fieldLimit) { 528 throw InvalidProtocolBufferException.truncatedMessage(); 529 } 530 return position; 531 } 532 533 /** Decodes a packed double field. Returns the position after all read values. */ decodePackedDoubleList( byte[] data, int position, ProtobufList<?> list, Registers registers)534 static int decodePackedDoubleList( 535 byte[] data, int position, ProtobufList<?> list, Registers registers) 536 throws InvalidProtocolBufferException { 537 final DoubleArrayList output = (DoubleArrayList) list; 538 position = decodeVarint32(data, position, registers); 539 final int packedDataByteSize = registers.int1; 540 final int fieldLimit = position + packedDataByteSize; 541 if (fieldLimit > data.length) { 542 throw InvalidProtocolBufferException.truncatedMessage(); 543 } 544 output.ensureCapacity(output.size() + packedDataByteSize / 8); 545 while (position < fieldLimit) { 546 output.addDouble(decodeDouble(data, position)); 547 position += 8; 548 } 549 if (position != fieldLimit) { 550 throw InvalidProtocolBufferException.truncatedMessage(); 551 } 552 return position; 553 } 554 555 /** Decodes a packed boolean field. Returns the position after all read values. */ decodePackedBoolList( byte[] data, int position, ProtobufList<?> list, Registers registers)556 static int decodePackedBoolList( 557 byte[] data, int position, ProtobufList<?> list, Registers registers) 558 throws InvalidProtocolBufferException { 559 final BooleanArrayList output = (BooleanArrayList) list; 560 position = decodeVarint32(data, position, registers); 561 final int fieldLimit = position + registers.int1; 562 while (position < fieldLimit) { 563 position = decodeVarint64(data, position, registers); 564 output.addBoolean(registers.long1 != 0); 565 } 566 if (position != fieldLimit) { 567 throw InvalidProtocolBufferException.truncatedMessage(); 568 } 569 return position; 570 } 571 572 /** Decodes a packed sint32 field. Returns the position after all read values. */ decodePackedSInt32List( byte[] data, int position, ProtobufList<?> list, Registers registers)573 static int decodePackedSInt32List( 574 byte[] data, int position, ProtobufList<?> list, Registers registers) 575 throws InvalidProtocolBufferException { 576 final IntArrayList output = (IntArrayList) list; 577 position = decodeVarint32(data, position, registers); 578 final int fieldLimit = position + registers.int1; 579 while (position < fieldLimit) { 580 position = decodeVarint32(data, position, registers); 581 output.addInt(CodedInputStream.decodeZigZag32(registers.int1)); 582 } 583 if (position != fieldLimit) { 584 throw InvalidProtocolBufferException.truncatedMessage(); 585 } 586 return position; 587 } 588 589 /** Decodes a packed sint64 field. Returns the position after all read values. */ decodePackedSInt64List( byte[] data, int position, ProtobufList<?> list, Registers registers)590 static int decodePackedSInt64List( 591 byte[] data, int position, ProtobufList<?> list, Registers registers) 592 throws InvalidProtocolBufferException { 593 final LongArrayList output = (LongArrayList) list; 594 position = decodeVarint32(data, position, registers); 595 final int fieldLimit = position + registers.int1; 596 while (position < fieldLimit) { 597 position = decodeVarint64(data, position, registers); 598 output.addLong(CodedInputStream.decodeZigZag64(registers.long1)); 599 } 600 if (position != fieldLimit) { 601 throw InvalidProtocolBufferException.truncatedMessage(); 602 } 603 return position; 604 } 605 606 /** Decodes a repeated string field. Returns the position after all read values. */ 607 @SuppressWarnings("unchecked") decodeStringList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)608 static int decodeStringList( 609 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 610 throws InvalidProtocolBufferException { 611 final ProtobufList<String> output = (ProtobufList<String>) list; 612 position = decodeVarint32(data, position, registers); 613 final int length = registers.int1; 614 if (length < 0) { 615 throw InvalidProtocolBufferException.negativeSize(); 616 } else if (length == 0) { 617 output.add(""); 618 } else { 619 String value = new String(data, position, length, Internal.UTF_8); 620 output.add(value); 621 position += length; 622 } 623 while (position < limit) { 624 int nextPosition = decodeVarint32(data, position, registers); 625 if (tag != registers.int1) { 626 break; 627 } 628 position = decodeVarint32(data, nextPosition, registers); 629 final int nextLength = registers.int1; 630 if (nextLength < 0) { 631 throw InvalidProtocolBufferException.negativeSize(); 632 } else if (nextLength == 0) { 633 output.add(""); 634 } else { 635 String value = new String(data, position, nextLength, Internal.UTF_8); 636 output.add(value); 637 position += nextLength; 638 } 639 } 640 return position; 641 } 642 643 /** 644 * Decodes a repeated string field with utf8 check. Returns the position after all read values. 645 */ 646 @SuppressWarnings("unchecked") decodeStringListRequireUtf8( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)647 static int decodeStringListRequireUtf8( 648 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 649 throws InvalidProtocolBufferException { 650 final ProtobufList<String> output = (ProtobufList<String>) list; 651 position = decodeVarint32(data, position, registers); 652 final int length = registers.int1; 653 if (length < 0) { 654 throw InvalidProtocolBufferException.negativeSize(); 655 } else if (length == 0) { 656 output.add(""); 657 } else { 658 if (!Utf8.isValidUtf8(data, position, position + length)) { 659 throw InvalidProtocolBufferException.invalidUtf8(); 660 } 661 String value = new String(data, position, length, Internal.UTF_8); 662 output.add(value); 663 position += length; 664 } 665 while (position < limit) { 666 int nextPosition = decodeVarint32(data, position, registers); 667 if (tag != registers.int1) { 668 break; 669 } 670 position = decodeVarint32(data, nextPosition, registers); 671 final int nextLength = registers.int1; 672 if (nextLength < 0) { 673 throw InvalidProtocolBufferException.negativeSize(); 674 } else if (nextLength == 0) { 675 output.add(""); 676 } else { 677 if (!Utf8.isValidUtf8(data, position, position + nextLength)) { 678 throw InvalidProtocolBufferException.invalidUtf8(); 679 } 680 String value = new String(data, position, nextLength, Internal.UTF_8); 681 output.add(value); 682 position += nextLength; 683 } 684 } 685 return position; 686 } 687 688 /** Decodes a repeated bytes field. Returns the position after all read values. */ 689 @SuppressWarnings("unchecked") decodeBytesList( int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)690 static int decodeBytesList( 691 int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers) 692 throws InvalidProtocolBufferException { 693 final ProtobufList<ByteString> output = (ProtobufList<ByteString>) list; 694 position = decodeVarint32(data, position, registers); 695 final int length = registers.int1; 696 if (length < 0) { 697 throw InvalidProtocolBufferException.negativeSize(); 698 } else if (length > data.length - position) { 699 throw InvalidProtocolBufferException.truncatedMessage(); 700 } else if (length == 0) { 701 output.add(ByteString.EMPTY); 702 } else { 703 output.add(ByteString.copyFrom(data, position, length)); 704 position += length; 705 } 706 while (position < limit) { 707 int nextPosition = decodeVarint32(data, position, registers); 708 if (tag != registers.int1) { 709 break; 710 } 711 position = decodeVarint32(data, nextPosition, registers); 712 final int nextLength = registers.int1; 713 if (nextLength < 0) { 714 throw InvalidProtocolBufferException.negativeSize(); 715 } else if (nextLength > data.length - position) { 716 throw InvalidProtocolBufferException.truncatedMessage(); 717 } else if (nextLength == 0) { 718 output.add(ByteString.EMPTY); 719 } else { 720 output.add(ByteString.copyFrom(data, position, nextLength)); 721 position += nextLength; 722 } 723 } 724 return position; 725 } 726 727 /** 728 * Decodes a repeated message field 729 * 730 * @return The position of after read all messages 731 */ 732 @SuppressWarnings({"unchecked"}) decodeMessageList( Schema<?> schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)733 static int decodeMessageList( 734 Schema<?> schema, 735 int tag, 736 byte[] data, 737 int position, 738 int limit, 739 ProtobufList<?> list, 740 Registers registers) 741 throws IOException { 742 final ProtobufList<Object> output = (ProtobufList<Object>) list; 743 position = decodeMessageField(schema, data, position, limit, registers); 744 output.add(registers.object1); 745 while (position < limit) { 746 int nextPosition = decodeVarint32(data, position, registers); 747 if (tag != registers.int1) { 748 break; 749 } 750 position = decodeMessageField(schema, data, nextPosition, limit, registers); 751 output.add(registers.object1); 752 } 753 return position; 754 } 755 756 /** 757 * Decodes a repeated group field 758 * 759 * @return The position of after read all groups 760 */ 761 @SuppressWarnings({"unchecked", "rawtypes"}) decodeGroupList( Schema schema, int tag, byte[] data, int position, int limit, ProtobufList<?> list, Registers registers)762 static int decodeGroupList( 763 Schema schema, 764 int tag, 765 byte[] data, 766 int position, 767 int limit, 768 ProtobufList<?> list, 769 Registers registers) 770 throws IOException { 771 final ProtobufList<Object> output = (ProtobufList<Object>) list; 772 final int endgroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 773 position = decodeGroupField(schema, data, position, limit, endgroup, registers); 774 output.add(registers.object1); 775 while (position < limit) { 776 int nextPosition = decodeVarint32(data, position, registers); 777 if (tag != registers.int1) { 778 break; 779 } 780 position = decodeGroupField(schema, data, nextPosition, limit, endgroup, registers); 781 output.add(registers.object1); 782 } 783 return position; 784 } 785 decodeExtensionOrUnknownField( int tag, byte[] data, int position, int limit, Object message, MessageLite defaultInstance, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)786 static int decodeExtensionOrUnknownField( 787 int tag, byte[] data, int position, int limit, 788 Object message, 789 MessageLite defaultInstance, 790 UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, 791 Registers registers) 792 throws IOException { 793 final int number = tag >>> 3; 794 GeneratedMessageLite.GeneratedExtension extension = 795 registers.extensionRegistry.findLiteExtensionByNumber(defaultInstance, number); 796 if (extension == null) { 797 return decodeUnknownField( 798 tag, data, position, limit, getMutableUnknownFields(message), registers); 799 } else { 800 // TODO: remove the unused variable 801 FieldSet<ExtensionDescriptor> unused = 802 ((GeneratedMessageLite.ExtendableMessage<?, ?>) message).ensureExtensionsAreMutable(); 803 return decodeExtension( 804 tag, data, position, limit, (GeneratedMessageLite.ExtendableMessage) message, 805 extension, unknownFieldSchema, registers); 806 } 807 } 808 decodeExtension( int tag, byte[] data, int position, int limit, GeneratedMessageLite.ExtendableMessage<?, ?> message, GeneratedMessageLite.GeneratedExtension<?, ?> extension, UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, Registers registers)809 static int decodeExtension( 810 int tag, 811 byte[] data, 812 int position, 813 int limit, 814 GeneratedMessageLite.ExtendableMessage<?, ?> message, 815 GeneratedMessageLite.GeneratedExtension<?, ?> extension, 816 UnknownFieldSchema<UnknownFieldSetLite, UnknownFieldSetLite> unknownFieldSchema, 817 Registers registers) 818 throws IOException { 819 final FieldSet<GeneratedMessageLite.ExtensionDescriptor> extensions = message.extensions; 820 final int fieldNumber = tag >>> 3; 821 if (extension.descriptor.isRepeated() && extension.descriptor.isPacked()) { 822 switch (extension.getLiteType()) { 823 case DOUBLE: 824 { 825 DoubleArrayList list = new DoubleArrayList(); 826 position = decodePackedDoubleList(data, position, list, registers); 827 extensions.setField(extension.descriptor, list); 828 break; 829 } 830 case FLOAT: 831 { 832 FloatArrayList list = new FloatArrayList(); 833 position = decodePackedFloatList(data, position, list, registers); 834 extensions.setField(extension.descriptor, list); 835 break; 836 } 837 case INT64: 838 case UINT64: 839 { 840 LongArrayList list = new LongArrayList(); 841 position = decodePackedVarint64List(data, position, list, registers); 842 extensions.setField(extension.descriptor, list); 843 break; 844 } 845 case INT32: 846 case UINT32: 847 { 848 IntArrayList list = new IntArrayList(); 849 position = decodePackedVarint32List(data, position, list, registers); 850 extensions.setField(extension.descriptor, list); 851 break; 852 } 853 case FIXED64: 854 case SFIXED64: 855 { 856 LongArrayList list = new LongArrayList(); 857 position = decodePackedFixed64List(data, position, list, registers); 858 extensions.setField(extension.descriptor, list); 859 break; 860 } 861 case FIXED32: 862 case SFIXED32: 863 { 864 IntArrayList list = new IntArrayList(); 865 position = decodePackedFixed32List(data, position, list, registers); 866 extensions.setField(extension.descriptor, list); 867 break; 868 } 869 case BOOL: 870 { 871 BooleanArrayList list = new BooleanArrayList(); 872 position = decodePackedBoolList(data, position, list, registers); 873 extensions.setField(extension.descriptor, list); 874 break; 875 } 876 case SINT32: 877 { 878 IntArrayList list = new IntArrayList(); 879 position = decodePackedSInt32List(data, position, list, registers); 880 extensions.setField(extension.descriptor, list); 881 break; 882 } 883 case SINT64: 884 { 885 LongArrayList list = new LongArrayList(); 886 position = decodePackedSInt64List(data, position, list, registers); 887 extensions.setField(extension.descriptor, list); 888 break; 889 } 890 case ENUM: 891 { 892 IntArrayList list = new IntArrayList(); 893 position = decodePackedVarint32List(data, position, list, registers); 894 SchemaUtil.filterUnknownEnumList( 895 message, 896 fieldNumber, 897 list, 898 extension.descriptor.getEnumType(), 899 null, 900 unknownFieldSchema); 901 extensions.setField(extension.descriptor, list); 902 break; 903 } 904 default: 905 throw new IllegalStateException( 906 "Type cannot be packed: " + extension.descriptor.getLiteType()); 907 } 908 } else { 909 Object value = null; 910 // Enum is a special case because unknown enum values will be put into UnknownFieldSetLite. 911 if (extension.getLiteType() == WireFormat.FieldType.ENUM) { 912 position = decodeVarint32(data, position, registers); 913 Object enumValue = extension.descriptor.getEnumType().findValueByNumber(registers.int1); 914 if (enumValue == null) { 915 SchemaUtil.storeUnknownEnum( 916 message, fieldNumber, registers.int1, null, unknownFieldSchema); 917 return position; 918 } 919 // Note, we store the integer value instead of the actual enum object in FieldSet. 920 // This is also different from full-runtime where we store EnumValueDescriptor. 921 value = registers.int1; 922 } else { 923 switch (extension.getLiteType()) { 924 case DOUBLE: 925 value = decodeDouble(data, position); 926 position += 8; 927 break; 928 case FLOAT: 929 value = decodeFloat(data, position); 930 position += 4; 931 break; 932 case INT64: 933 case UINT64: 934 position = decodeVarint64(data, position, registers); 935 value = registers.long1; 936 break; 937 case INT32: 938 case UINT32: 939 position = decodeVarint32(data, position, registers); 940 value = registers.int1; 941 break; 942 case FIXED64: 943 case SFIXED64: 944 value = decodeFixed64(data, position); 945 position += 8; 946 break; 947 case FIXED32: 948 case SFIXED32: 949 value = decodeFixed32(data, position); 950 position += 4; 951 break; 952 case BOOL: 953 position = decodeVarint64(data, position, registers); 954 value = (registers.long1 != 0); 955 break; 956 case BYTES: 957 position = decodeBytes(data, position, registers); 958 value = registers.object1; 959 break; 960 case SINT32: 961 position = decodeVarint32(data, position, registers); 962 value = CodedInputStream.decodeZigZag32(registers.int1); 963 break; 964 case SINT64: 965 position = decodeVarint64(data, position, registers); 966 value = CodedInputStream.decodeZigZag64(registers.long1); 967 break; 968 case STRING: 969 position = decodeString(data, position, registers); 970 value = registers.object1; 971 break; 972 case GROUP: 973 { 974 final int endTag = (fieldNumber << 3) | WireFormat.WIRETYPE_END_GROUP; 975 final Schema fieldSchema = 976 Protobuf.getInstance() 977 .schemaFor(extension.getMessageDefaultInstance().getClass()); 978 if (extension.isRepeated()) { 979 position = decodeGroupField(fieldSchema, data, position, limit, endTag, registers); 980 extensions.addRepeatedField(extension.descriptor, registers.object1); 981 } else { 982 Object oldValue = extensions.getField(extension.descriptor); 983 if (oldValue == null) { 984 oldValue = fieldSchema.newInstance(); 985 extensions.setField(extension.descriptor, oldValue); 986 } 987 position = 988 mergeGroupField( 989 oldValue, fieldSchema, data, position, limit, endTag, registers); 990 } 991 return position; 992 } 993 case MESSAGE: 994 { 995 final Schema fieldSchema = 996 Protobuf.getInstance() 997 .schemaFor(extension.getMessageDefaultInstance().getClass()); 998 if (extension.isRepeated()) { 999 position = decodeMessageField(fieldSchema, data, position, limit, registers); 1000 extensions.addRepeatedField(extension.descriptor, registers.object1); 1001 } else { 1002 Object oldValue = extensions.getField(extension.descriptor); 1003 if (oldValue == null) { 1004 oldValue = fieldSchema.newInstance(); 1005 extensions.setField(extension.descriptor, oldValue); 1006 } 1007 position = 1008 mergeMessageField(oldValue, fieldSchema, data, position, limit, registers); 1009 } 1010 return position; 1011 } 1012 case ENUM: 1013 throw new IllegalStateException("Shouldn't reach here."); 1014 } 1015 } 1016 if (extension.isRepeated()) { 1017 extensions.addRepeatedField(extension.descriptor, value); 1018 } else { 1019 extensions.setField(extension.descriptor, value); 1020 } 1021 } 1022 return position; 1023 } 1024 1025 /** Decodes an unknown field. */ decodeUnknownField( int tag, byte[] data, int position, int limit, UnknownFieldSetLite unknownFields, Registers registers)1026 static int decodeUnknownField( 1027 int tag, 1028 byte[] data, 1029 int position, 1030 int limit, 1031 UnknownFieldSetLite unknownFields, 1032 Registers registers) 1033 throws InvalidProtocolBufferException { 1034 if (WireFormat.getTagFieldNumber(tag) == 0) { 1035 throw InvalidProtocolBufferException.invalidTag(); 1036 } 1037 switch (WireFormat.getTagWireType(tag)) { 1038 case WireFormat.WIRETYPE_VARINT: 1039 position = decodeVarint64(data, position, registers); 1040 unknownFields.storeField(tag, registers.long1); 1041 return position; 1042 case WireFormat.WIRETYPE_FIXED32: 1043 unknownFields.storeField(tag, decodeFixed32(data, position)); 1044 return position + 4; 1045 case WireFormat.WIRETYPE_FIXED64: 1046 unknownFields.storeField(tag, decodeFixed64(data, position)); 1047 return position + 8; 1048 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1049 position = decodeVarint32(data, position, registers); 1050 final int length = registers.int1; 1051 if (length < 0) { 1052 throw InvalidProtocolBufferException.negativeSize(); 1053 } else if (length > data.length - position) { 1054 throw InvalidProtocolBufferException.truncatedMessage(); 1055 } else if (length == 0) { 1056 unknownFields.storeField(tag, ByteString.EMPTY); 1057 } else { 1058 unknownFields.storeField(tag, ByteString.copyFrom(data, position, length)); 1059 } 1060 return position + length; 1061 case WireFormat.WIRETYPE_START_GROUP: 1062 final UnknownFieldSetLite child = UnknownFieldSetLite.newInstance(); 1063 final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 1064 int lastTag = 0; 1065 registers.recursionDepth++; 1066 checkRecursionLimit(registers.recursionDepth); 1067 while (position < limit) { 1068 position = decodeVarint32(data, position, registers); 1069 lastTag = registers.int1; 1070 if (lastTag == endGroup) { 1071 break; 1072 } 1073 position = decodeUnknownField(lastTag, data, position, limit, child, registers); 1074 } 1075 registers.recursionDepth--; 1076 if (position > limit || lastTag != endGroup) { 1077 throw InvalidProtocolBufferException.parseFailure(); 1078 } 1079 unknownFields.storeField(tag, child); 1080 return position; 1081 default: 1082 throw InvalidProtocolBufferException.invalidTag(); 1083 } 1084 } 1085 1086 /** Skips an unknown field. */ skipField(int tag, byte[] data, int position, int limit, Registers registers)1087 static int skipField(int tag, byte[] data, int position, int limit, Registers registers) 1088 throws InvalidProtocolBufferException { 1089 if (WireFormat.getTagFieldNumber(tag) == 0) { 1090 throw InvalidProtocolBufferException.invalidTag(); 1091 } 1092 switch (WireFormat.getTagWireType(tag)) { 1093 case WireFormat.WIRETYPE_VARINT: 1094 position = decodeVarint64(data, position, registers); 1095 return position; 1096 case WireFormat.WIRETYPE_FIXED32: 1097 return position + 4; 1098 case WireFormat.WIRETYPE_FIXED64: 1099 return position + 8; 1100 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 1101 position = decodeVarint32(data, position, registers); 1102 return position + registers.int1; 1103 case WireFormat.WIRETYPE_START_GROUP: 1104 final int endGroup = (tag & ~0x7) | WireFormat.WIRETYPE_END_GROUP; 1105 int lastTag = 0; 1106 while (position < limit) { 1107 position = decodeVarint32(data, position, registers); 1108 lastTag = registers.int1; 1109 if (lastTag == endGroup) { 1110 break; 1111 } 1112 position = skipField(lastTag, data, position, limit, registers); 1113 } 1114 if (position > limit || lastTag != endGroup) { 1115 throw InvalidProtocolBufferException.parseFailure(); 1116 } 1117 return position; 1118 default: 1119 throw InvalidProtocolBufferException.invalidTag(); 1120 } 1121 } 1122 1123 /** 1124 * Set the maximum recursion limit that ArrayDecoders will allow. An exception will be thrown if 1125 * the depth of the message exceeds this limit. 1126 */ setRecursionLimit(int limit)1127 public static void setRecursionLimit(int limit) { 1128 recursionLimit = limit; 1129 } 1130 checkRecursionLimit(int depth)1131 private static void checkRecursionLimit(int depth) throws InvalidProtocolBufferException { 1132 if (depth >= recursionLimit) { 1133 throw InvalidProtocolBufferException.recursionLimitExceeded(); 1134 } 1135 } 1136 } 1137