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 31package com.google.protobuf; 32 33import java.io.ByteArrayOutputStream; 34import java.io.IOException; 35import java.io.InputStream; 36import java.nio.ByteBuffer; 37import java.util.ArrayList; 38import java.util.Arrays; 39import java.util.List; 40 41/** 42 * Reads and decodes protocol message fields. 43 * 44 * This class contains two kinds of methods: methods that read specific 45 * protocol message constructs and field types (e.g. {@link #readTag()} and 46 * {@link #readInt32()}) and methods that read low-level values (e.g. 47 * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading 48 * encoded protocol messages, you should use the former methods, but if you are 49 * reading some other format of your own design, use the latter. 50 * 51 * @author kenton@google.com Kenton Varda 52 */ 53public final class CodedInputStream { 54 /** 55 * Create a new CodedInputStream wrapping the given InputStream. 56 */ 57 public static CodedInputStream newInstance(final InputStream input) { 58 return new CodedInputStream(input); 59 } 60 61 /** 62 * Create a new CodedInputStream wrapping the given byte array. 63 */ 64 public static CodedInputStream newInstance(final byte[] buf) { 65 return newInstance(buf, 0, buf.length); 66 } 67 68 /** 69 * Create a new CodedInputStream wrapping the given byte array slice. 70 */ 71 public static CodedInputStream newInstance(final byte[] buf, final int off, 72 final int len) { 73 CodedInputStream result = new CodedInputStream(buf, off, len); 74 try { 75 // Some uses of CodedInputStream can be more efficient if they know 76 // exactly how many bytes are available. By pushing the end point of the 77 // buffer as a limit, we allow them to get this information via 78 // getBytesUntilLimit(). Pushing a limit that we know is at the end of 79 // the stream can never hurt, since we can never past that point anyway. 80 result.pushLimit(len); 81 } catch (InvalidProtocolBufferException ex) { 82 // The only reason pushLimit() might throw an exception here is if len 83 // is negative. Normally pushLimit()'s parameter comes directly off the 84 // wire, so it's important to catch exceptions in case of corrupt or 85 // malicious data. However, in this case, we expect that len is not a 86 // user-supplied value, so we can assume that it being negative indicates 87 // a programming error. Therefore, throwing an unchecked exception is 88 // appropriate. 89 throw new IllegalArgumentException(ex); 90 } 91 return result; 92 } 93 94 /** 95 * Create a new CodedInputStream wrapping the given ByteBuffer. The data 96 * starting from the ByteBuffer's current position to its limit will be read. 97 * The returned CodedInputStream may or may not share the underlying data 98 * in the ByteBuffer, therefore the ByteBuffer cannot be changed while the 99 * CodedInputStream is in use. 100 * Note that the ByteBuffer's position won't be changed by this function. 101 * Concurrent calls with the same ByteBuffer object are safe if no other 102 * thread is trying to alter the ByteBuffer's status. 103 */ 104 public static CodedInputStream newInstance(ByteBuffer buf) { 105 if (buf.hasArray()) { 106 return newInstance(buf.array(), buf.arrayOffset() + buf.position(), 107 buf.remaining()); 108 } else { 109 ByteBuffer temp = buf.duplicate(); 110 byte[] buffer = new byte[temp.remaining()]; 111 temp.get(buffer); 112 return newInstance(buffer); 113 } 114 } 115 116 /** 117 * Create a new CodedInputStream wrapping a LiteralByteString. 118 */ 119 static CodedInputStream newInstance(LiteralByteString byteString) { 120 CodedInputStream result = new CodedInputStream(byteString); 121 try { 122 // Some uses of CodedInputStream can be more efficient if they know 123 // exactly how many bytes are available. By pushing the end point of the 124 // buffer as a limit, we allow them to get this information via 125 // getBytesUntilLimit(). Pushing a limit that we know is at the end of 126 // the stream can never hurt, since we can never past that point anyway. 127 result.pushLimit(byteString.size()); 128 } catch (InvalidProtocolBufferException ex) { 129 // The only reason pushLimit() might throw an exception here is if len 130 // is negative. Normally pushLimit()'s parameter comes directly off the 131 // wire, so it's important to catch exceptions in case of corrupt or 132 // malicious data. However, in this case, we expect that len is not a 133 // user-supplied value, so we can assume that it being negative indicates 134 // a programming error. Therefore, throwing an unchecked exception is 135 // appropriate. 136 throw new IllegalArgumentException(ex); 137 } 138 return result; 139 } 140 141 // ----------------------------------------------------------------- 142 143 /** 144 * Attempt to read a field tag, returning zero if we have reached EOF. 145 * Protocol message parsers use this to read tags, since a protocol message 146 * may legally end wherever a tag occurs, and zero is not a valid tag number. 147 */ 148 public int readTag() throws IOException { 149 if (isAtEnd()) { 150 lastTag = 0; 151 return 0; 152 } 153 154 lastTag = readRawVarint32(); 155 if (WireFormat.getTagFieldNumber(lastTag) == 0) { 156 // If we actually read zero (or any tag number corresponding to field 157 // number zero), that's not a valid tag. 158 throw InvalidProtocolBufferException.invalidTag(); 159 } 160 return lastTag; 161 } 162 163 /** 164 * Verifies that the last call to readTag() returned the given tag value. 165 * This is used to verify that a nested group ended with the correct 166 * end tag. 167 * 168 * @throws InvalidProtocolBufferException {@code value} does not match the 169 * last tag. 170 */ 171 public void checkLastTagWas(final int value) 172 throws InvalidProtocolBufferException { 173 if (lastTag != value) { 174 throw InvalidProtocolBufferException.invalidEndTag(); 175 } 176 } 177 178 public int getLastTag() { 179 return lastTag; 180 } 181 182 /** 183 * Reads and discards a single field, given its tag value. 184 * 185 * @return {@code false} if the tag is an endgroup tag, in which case 186 * nothing is skipped. Otherwise, returns {@code true}. 187 */ 188 public boolean skipField(final int tag) throws IOException { 189 switch (WireFormat.getTagWireType(tag)) { 190 case WireFormat.WIRETYPE_VARINT: 191 skipRawVarint(); 192 return true; 193 case WireFormat.WIRETYPE_FIXED64: 194 skipRawBytes(8); 195 return true; 196 case WireFormat.WIRETYPE_LENGTH_DELIMITED: 197 skipRawBytes(readRawVarint32()); 198 return true; 199 case WireFormat.WIRETYPE_START_GROUP: 200 skipMessage(); 201 checkLastTagWas( 202 WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), 203 WireFormat.WIRETYPE_END_GROUP)); 204 return true; 205 case WireFormat.WIRETYPE_END_GROUP: 206 return false; 207 case WireFormat.WIRETYPE_FIXED32: 208 skipRawBytes(4); 209 return true; 210 default: 211 throw InvalidProtocolBufferException.invalidWireType(); 212 } 213 } 214 215 /** 216 * Reads a single field and writes it to output in wire format, 217 * given its tag value. 218 * 219 * @return {@code false} if the tag is an endgroup tag, in which case 220 * nothing is skipped. Otherwise, returns {@code true}. 221 */ 222 public boolean skipField(final int tag, final CodedOutputStream output) 223 throws IOException { 224 switch (WireFormat.getTagWireType(tag)) { 225 case WireFormat.WIRETYPE_VARINT: { 226 long value = readInt64(); 227 output.writeRawVarint32(tag); 228 output.writeUInt64NoTag(value); 229 return true; 230 } 231 case WireFormat.WIRETYPE_FIXED64: { 232 long value = readRawLittleEndian64(); 233 output.writeRawVarint32(tag); 234 output.writeFixed64NoTag(value); 235 return true; 236 } 237 case WireFormat.WIRETYPE_LENGTH_DELIMITED: { 238 ByteString value = readBytes(); 239 output.writeRawVarint32(tag); 240 output.writeBytesNoTag(value); 241 return true; 242 } 243 case WireFormat.WIRETYPE_START_GROUP: { 244 output.writeRawVarint32(tag); 245 skipMessage(output); 246 int endtag = WireFormat.makeTag(WireFormat.getTagFieldNumber(tag), 247 WireFormat.WIRETYPE_END_GROUP); 248 checkLastTagWas(endtag); 249 output.writeRawVarint32(endtag); 250 return true; 251 } 252 case WireFormat.WIRETYPE_END_GROUP: { 253 return false; 254 } 255 case WireFormat.WIRETYPE_FIXED32: { 256 int value = readRawLittleEndian32(); 257 output.writeRawVarint32(tag); 258 output.writeFixed32NoTag(value); 259 return true; 260 } 261 default: 262 throw InvalidProtocolBufferException.invalidWireType(); 263 } 264 } 265 266 /** 267 * Reads and discards an entire message. This will read either until EOF 268 * or until an endgroup tag, whichever comes first. 269 */ 270 public void skipMessage() throws IOException { 271 while (true) { 272 final int tag = readTag(); 273 if (tag == 0 || !skipField(tag)) { 274 return; 275 } 276 } 277 } 278 279 /** 280 * Reads an entire message and writes it to output in wire format. 281 * This will read either until EOF or until an endgroup tag, 282 * whichever comes first. 283 */ 284 public void skipMessage(CodedOutputStream output) throws IOException { 285 while (true) { 286 final int tag = readTag(); 287 if (tag == 0 || !skipField(tag, output)) { 288 return; 289 } 290 } 291 } 292 293 /** 294 * Collects the bytes skipped and returns the data in a ByteBuffer. 295 */ 296 private class SkippedDataSink implements RefillCallback { 297 private int lastPos = bufferPos; 298 private ByteArrayOutputStream byteArrayStream; 299 300 @Override 301 public void onRefill() { 302 if (byteArrayStream == null) { 303 byteArrayStream = new ByteArrayOutputStream(); 304 } 305 byteArrayStream.write(buffer, lastPos, bufferPos - lastPos); 306 lastPos = 0; 307 } 308 309 /** 310 * Gets skipped data in a ByteBuffer. This method should only be 311 * called once. 312 */ 313 ByteBuffer getSkippedData() { 314 if (byteArrayStream == null) { 315 return ByteBuffer.wrap(buffer, lastPos, bufferPos - lastPos); 316 } else { 317 byteArrayStream.write(buffer, lastPos, bufferPos); 318 return ByteBuffer.wrap(byteArrayStream.toByteArray()); 319 } 320 } 321 } 322 323 324 // ----------------------------------------------------------------- 325 326 /** Read a {@code double} field value from the stream. */ 327 public double readDouble() throws IOException { 328 return Double.longBitsToDouble(readRawLittleEndian64()); 329 } 330 331 /** Read a {@code float} field value from the stream. */ 332 public float readFloat() throws IOException { 333 return Float.intBitsToFloat(readRawLittleEndian32()); 334 } 335 336 /** Read a {@code uint64} field value from the stream. */ 337 public long readUInt64() throws IOException { 338 return readRawVarint64(); 339 } 340 341 /** Read an {@code int64} field value from the stream. */ 342 public long readInt64() throws IOException { 343 return readRawVarint64(); 344 } 345 346 /** Read an {@code int32} field value from the stream. */ 347 public int readInt32() throws IOException { 348 return readRawVarint32(); 349 } 350 351 /** Read a {@code fixed64} field value from the stream. */ 352 public long readFixed64() throws IOException { 353 return readRawLittleEndian64(); 354 } 355 356 /** Read a {@code fixed32} field value from the stream. */ 357 public int readFixed32() throws IOException { 358 return readRawLittleEndian32(); 359 } 360 361 /** Read a {@code bool} field value from the stream. */ 362 public boolean readBool() throws IOException { 363 return readRawVarint64() != 0; 364 } 365 366 /** 367 * Read a {@code string} field value from the stream. 368 * If the stream contains malformed UTF-8, 369 * replace the offending bytes with the standard UTF-8 replacement character. 370 */ 371 public String readString() throws IOException { 372 final int size = readRawVarint32(); 373 if (size <= (bufferSize - bufferPos) && size > 0) { 374 // Fast path: We already have the bytes in a contiguous buffer, so 375 // just copy directly from it. 376 final String result = new String(buffer, bufferPos, size, "UTF-8"); 377 bufferPos += size; 378 return result; 379 } else if (size == 0) { 380 return ""; 381 } else { 382 // Slow path: Build a byte array first then copy it. 383 return new String(readRawBytesSlowPath(size), "UTF-8"); 384 } 385 } 386 387 /** 388 * Read a {@code string} field value from the stream. 389 * If the stream contains malformed UTF-8, 390 * throw exception {@link InvalidProtocolBufferException}. 391 */ 392 public String readStringRequireUtf8() throws IOException { 393 final int size = readRawVarint32(); 394 final byte[] bytes; 395 int pos = bufferPos; 396 if (size <= (bufferSize - pos) && size > 0) { 397 // Fast path: We already have the bytes in a contiguous buffer, so 398 // just copy directly from it. 399 bytes = buffer; 400 bufferPos = pos + size; 401 } else if (size == 0) { 402 return ""; 403 } else { 404 // Slow path: Build a byte array first then copy it. 405 bytes = readRawBytesSlowPath(size); 406 pos = 0; 407 } 408 // TODO(martinrb): We could save a pass by validating while decoding. 409 if (!Utf8.isValidUtf8(bytes, pos, pos + size)) { 410 throw InvalidProtocolBufferException.invalidUtf8(); 411 } 412 return new String(bytes, pos, size, "UTF-8"); 413 } 414 415 /** Read a {@code group} field value from the stream. */ 416 public void readGroup(final int fieldNumber, 417 final MessageLite.Builder builder, 418 final ExtensionRegistryLite extensionRegistry) 419 throws IOException { 420 if (recursionDepth >= recursionLimit) { 421 throw InvalidProtocolBufferException.recursionLimitExceeded(); 422 } 423 ++recursionDepth; 424 builder.mergeFrom(this, extensionRegistry); 425 checkLastTagWas( 426 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 427 --recursionDepth; 428 } 429 430 431 /** Read a {@code group} field value from the stream. */ 432 public <T extends MessageLite> T readGroup( 433 final int fieldNumber, 434 final Parser<T> parser, 435 final ExtensionRegistryLite extensionRegistry) 436 throws IOException { 437 if (recursionDepth >= recursionLimit) { 438 throw InvalidProtocolBufferException.recursionLimitExceeded(); 439 } 440 ++recursionDepth; 441 T result = parser.parsePartialFrom(this, extensionRegistry); 442 checkLastTagWas( 443 WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP)); 444 --recursionDepth; 445 return result; 446 } 447 448 /** 449 * Reads a {@code group} field value from the stream and merges it into the 450 * given {@link UnknownFieldSet}. 451 * 452 * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so 453 * you can just call {@link #readGroup}. 454 */ 455 @Deprecated 456 public void readUnknownGroup(final int fieldNumber, 457 final MessageLite.Builder builder) 458 throws IOException { 459 // We know that UnknownFieldSet will ignore any ExtensionRegistry so it 460 // is safe to pass null here. (We can't call 461 // ExtensionRegistry.getEmptyRegistry() because that would make this 462 // class depend on ExtensionRegistry, which is not part of the lite 463 // library.) 464 readGroup(fieldNumber, builder, null); 465 } 466 467 /** Read an embedded message field value from the stream. */ 468 public void readMessage(final MessageLite.Builder builder, 469 final ExtensionRegistryLite extensionRegistry) 470 throws IOException { 471 final int length = readRawVarint32(); 472 if (recursionDepth >= recursionLimit) { 473 throw InvalidProtocolBufferException.recursionLimitExceeded(); 474 } 475 final int oldLimit = pushLimit(length); 476 ++recursionDepth; 477 builder.mergeFrom(this, extensionRegistry); 478 checkLastTagWas(0); 479 --recursionDepth; 480 popLimit(oldLimit); 481 } 482 483 484 /** Read an embedded message field value from the stream. */ 485 public <T extends MessageLite> T readMessage( 486 final Parser<T> parser, 487 final ExtensionRegistryLite extensionRegistry) 488 throws IOException { 489 int length = readRawVarint32(); 490 if (recursionDepth >= recursionLimit) { 491 throw InvalidProtocolBufferException.recursionLimitExceeded(); 492 } 493 final int oldLimit = pushLimit(length); 494 ++recursionDepth; 495 T result = parser.parsePartialFrom(this, extensionRegistry); 496 checkLastTagWas(0); 497 --recursionDepth; 498 popLimit(oldLimit); 499 return result; 500 } 501 502 /** Read a {@code bytes} field value from the stream. */ 503 public ByteString readBytes() throws IOException { 504 final int size = readRawVarint32(); 505 if (size <= (bufferSize - bufferPos) && size > 0) { 506 // Fast path: We already have the bytes in a contiguous buffer, so 507 // just copy directly from it. 508 final ByteString result = bufferIsImmutable && enableAliasing 509 ? new BoundedByteString(buffer, bufferPos, size) 510 : ByteString.copyFrom(buffer, bufferPos, size); 511 bufferPos += size; 512 return result; 513 } else if (size == 0) { 514 return ByteString.EMPTY; 515 } else { 516 // Slow path: Build a byte array first then copy it. 517 return new LiteralByteString(readRawBytesSlowPath(size)); 518 } 519 } 520 521 /** Read a {@code bytes} field value from the stream. */ 522 public byte[] readByteArray() throws IOException { 523 final int size = readRawVarint32(); 524 if (size <= (bufferSize - bufferPos) && size > 0) { 525 // Fast path: We already have the bytes in a contiguous buffer, so 526 // just copy directly from it. 527 final byte[] result = 528 Arrays.copyOfRange(buffer, bufferPos, bufferPos + size); 529 bufferPos += size; 530 return result; 531 } else { 532 // Slow path: Build a byte array first then copy it. 533 return readRawBytesSlowPath(size); 534 } 535 } 536 537 /** Read a {@code bytes} field value from the stream. */ 538 public ByteBuffer readByteBuffer() throws IOException { 539 final int size = readRawVarint32(); 540 if (size <= (bufferSize - bufferPos) && size > 0) { 541 // Fast path: We already have the bytes in a contiguous buffer. 542 // When aliasing is enabled, we can return a ByteBuffer pointing directly 543 // into the underlying byte array without copy if the CodedInputStream is 544 // constructed from a byte array. If aliasing is disabled or the input is 545 // from an InputStream or ByteString, we have to make a copy of the bytes. 546 ByteBuffer result = input == null && !bufferIsImmutable && enableAliasing 547 ? ByteBuffer.wrap(buffer, bufferPos, size).slice() 548 : ByteBuffer.wrap(Arrays.copyOfRange( 549 buffer, bufferPos, bufferPos + size)); 550 bufferPos += size; 551 return result; 552 } else if (size == 0) { 553 return Internal.EMPTY_BYTE_BUFFER; 554 } else { 555 // Slow path: Build a byte array first then copy it. 556 return ByteBuffer.wrap(readRawBytesSlowPath(size)); 557 } 558 } 559 560 /** Read a {@code uint32} field value from the stream. */ 561 public int readUInt32() throws IOException { 562 return readRawVarint32(); 563 } 564 565 /** 566 * Read an enum field value from the stream. Caller is responsible 567 * for converting the numeric value to an actual enum. 568 */ 569 public int readEnum() throws IOException { 570 return readRawVarint32(); 571 } 572 573 /** Read an {@code sfixed32} field value from the stream. */ 574 public int readSFixed32() throws IOException { 575 return readRawLittleEndian32(); 576 } 577 578 /** Read an {@code sfixed64} field value from the stream. */ 579 public long readSFixed64() throws IOException { 580 return readRawLittleEndian64(); 581 } 582 583 /** Read an {@code sint32} field value from the stream. */ 584 public int readSInt32() throws IOException { 585 return decodeZigZag32(readRawVarint32()); 586 } 587 588 /** Read an {@code sint64} field value from the stream. */ 589 public long readSInt64() throws IOException { 590 return decodeZigZag64(readRawVarint64()); 591 } 592 593 // ================================================================= 594 595 /** 596 * Read a raw Varint from the stream. If larger than 32 bits, discard the 597 * upper bits. 598 */ 599 public int readRawVarint32() throws IOException { 600 // See implementation notes for readRawVarint64 601 fastpath: { 602 int pos = bufferPos; 603 604 if (bufferSize == pos) { 605 break fastpath; 606 } 607 608 final byte[] buffer = this.buffer; 609 int x; 610 if ((x = buffer[pos++]) >= 0) { 611 bufferPos = pos; 612 return x; 613 } else if (bufferSize - pos < 9) { 614 break fastpath; 615 } else if ((x ^= (buffer[pos++] << 7)) < 0L) { 616 x ^= (~0L << 7); 617 } else if ((x ^= (buffer[pos++] << 14)) >= 0L) { 618 x ^= (~0L << 7) ^ (~0L << 14); 619 } else if ((x ^= (buffer[pos++] << 21)) < 0L) { 620 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21); 621 } else { 622 int y = buffer[pos++]; 623 x ^= y << 28; 624 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 625 if (y < 0 && 626 buffer[pos++] < 0 && 627 buffer[pos++] < 0 && 628 buffer[pos++] < 0 && 629 buffer[pos++] < 0 && 630 buffer[pos++] < 0) { 631 break fastpath; // Will throw malformedVarint() 632 } 633 } 634 bufferPos = pos; 635 return x; 636 } 637 return (int) readRawVarint64SlowPath(); 638 } 639 640 private void skipRawVarint() throws IOException { 641 if (bufferSize - bufferPos >= 10) { 642 final byte[] buffer = this.buffer; 643 int pos = bufferPos; 644 for (int i = 0; i < 10; i++) { 645 if (buffer[pos++] >= 0) { 646 bufferPos = pos; 647 return; 648 } 649 } 650 } 651 skipRawVarintSlowPath(); 652 } 653 654 private void skipRawVarintSlowPath() throws IOException { 655 for (int i = 0; i < 10; i++) { 656 if (readRawByte() >= 0) { 657 return; 658 } 659 } 660 throw InvalidProtocolBufferException.malformedVarint(); 661 } 662 663 /** 664 * Reads a varint from the input one byte at a time, so that it does not 665 * read any bytes after the end of the varint. If you simply wrapped the 666 * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)} 667 * then you would probably end up reading past the end of the varint since 668 * CodedInputStream buffers its input. 669 */ 670 static int readRawVarint32(final InputStream input) throws IOException { 671 final int firstByte = input.read(); 672 if (firstByte == -1) { 673 throw InvalidProtocolBufferException.truncatedMessage(); 674 } 675 return readRawVarint32(firstByte, input); 676 } 677 678 /** 679 * Like {@link #readRawVarint32(InputStream)}, but expects that the caller 680 * has already read one byte. This allows the caller to determine if EOF 681 * has been reached before attempting to read. 682 */ 683 public static int readRawVarint32( 684 final int firstByte, final InputStream input) throws IOException { 685 if ((firstByte & 0x80) == 0) { 686 return firstByte; 687 } 688 689 int result = firstByte & 0x7f; 690 int offset = 7; 691 for (; offset < 32; offset += 7) { 692 final int b = input.read(); 693 if (b == -1) { 694 throw InvalidProtocolBufferException.truncatedMessage(); 695 } 696 result |= (b & 0x7f) << offset; 697 if ((b & 0x80) == 0) { 698 return result; 699 } 700 } 701 // Keep reading up to 64 bits. 702 for (; offset < 64; offset += 7) { 703 final int b = input.read(); 704 if (b == -1) { 705 throw InvalidProtocolBufferException.truncatedMessage(); 706 } 707 if ((b & 0x80) == 0) { 708 return result; 709 } 710 } 711 throw InvalidProtocolBufferException.malformedVarint(); 712 } 713 714 /** Read a raw Varint from the stream. */ 715 public long readRawVarint64() throws IOException { 716 // Implementation notes: 717 // 718 // Optimized for one-byte values, expected to be common. 719 // The particular code below was selected from various candidates 720 // empirically, by winning VarintBenchmark. 721 // 722 // Sign extension of (signed) Java bytes is usually a nuisance, but 723 // we exploit it here to more easily obtain the sign of bytes read. 724 // Instead of cleaning up the sign extension bits by masking eagerly, 725 // we delay until we find the final (positive) byte, when we clear all 726 // accumulated bits with one xor. We depend on javac to constant fold. 727 fastpath: { 728 int pos = bufferPos; 729 730 if (bufferSize == pos) { 731 break fastpath; 732 } 733 734 final byte[] buffer = this.buffer; 735 long x; 736 int y; 737 if ((y = buffer[pos++]) >= 0) { 738 bufferPos = pos; 739 return y; 740 } else if (bufferSize - pos < 9) { 741 break fastpath; 742 } else if ((x = y ^ (buffer[pos++] << 7)) < 0L) { 743 x ^= (~0L << 7); 744 } else if ((x ^= (buffer[pos++] << 14)) >= 0L) { 745 x ^= (~0L << 7) ^ (~0L << 14); 746 } else if ((x ^= (buffer[pos++] << 21)) < 0L) { 747 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21); 748 } else if ((x ^= ((long) buffer[pos++] << 28)) >= 0L) { 749 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28); 750 } else if ((x ^= ((long) buffer[pos++] << 35)) < 0L) { 751 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35); 752 } else if ((x ^= ((long) buffer[pos++] << 42)) >= 0L) { 753 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42); 754 } else if ((x ^= ((long) buffer[pos++] << 49)) < 0L) { 755 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42) 756 ^ (~0L << 49); 757 } else { 758 x ^= ((long) buffer[pos++] << 56); 759 x ^= (~0L << 7) ^ (~0L << 14) ^ (~0L << 21) ^ (~0L << 28) ^ (~0L << 35) ^ (~0L << 42) 760 ^ (~0L << 49) ^ (~0L << 56); 761 if (x < 0L) { 762 if (buffer[pos++] < 0L) { 763 break fastpath; // Will throw malformedVarint() 764 } 765 } 766 } 767 bufferPos = pos; 768 return x; 769 } 770 return readRawVarint64SlowPath(); 771 } 772 773 /** Variant of readRawVarint64 for when uncomfortably close to the limit. */ 774 /* Visible for testing */ 775 long readRawVarint64SlowPath() throws IOException { 776 long result = 0; 777 for (int shift = 0; shift < 64; shift += 7) { 778 final byte b = readRawByte(); 779 result |= (long) (b & 0x7F) << shift; 780 if ((b & 0x80) == 0) { 781 return result; 782 } 783 } 784 throw InvalidProtocolBufferException.malformedVarint(); 785 } 786 787 /** Read a 32-bit little-endian integer from the stream. */ 788 public int readRawLittleEndian32() throws IOException { 789 int pos = bufferPos; 790 791 // hand-inlined ensureAvailable(4); 792 if (bufferSize - pos < 4) { 793 refillBuffer(4); 794 pos = bufferPos; 795 } 796 797 final byte[] buffer = this.buffer; 798 bufferPos = pos + 4; 799 return (((buffer[pos] & 0xff)) | 800 ((buffer[pos + 1] & 0xff) << 8) | 801 ((buffer[pos + 2] & 0xff) << 16) | 802 ((buffer[pos + 3] & 0xff) << 24)); 803 } 804 805 /** Read a 64-bit little-endian integer from the stream. */ 806 public long readRawLittleEndian64() throws IOException { 807 int pos = bufferPos; 808 809 // hand-inlined ensureAvailable(8); 810 if (bufferSize - pos < 8) { 811 refillBuffer(8); 812 pos = bufferPos; 813 } 814 815 final byte[] buffer = this.buffer; 816 bufferPos = pos + 8; 817 return ((((long) buffer[pos] & 0xffL)) | 818 (((long) buffer[pos + 1] & 0xffL) << 8) | 819 (((long) buffer[pos + 2] & 0xffL) << 16) | 820 (((long) buffer[pos + 3] & 0xffL) << 24) | 821 (((long) buffer[pos + 4] & 0xffL) << 32) | 822 (((long) buffer[pos + 5] & 0xffL) << 40) | 823 (((long) buffer[pos + 6] & 0xffL) << 48) | 824 (((long) buffer[pos + 7] & 0xffL) << 56)); 825 } 826 827 /** 828 * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 829 * into values that can be efficiently encoded with varint. (Otherwise, 830 * negative values must be sign-extended to 64 bits to be varint encoded, 831 * thus always taking 10 bytes on the wire.) 832 * 833 * @param n An unsigned 32-bit integer, stored in a signed int because 834 * Java has no explicit unsigned support. 835 * @return A signed 32-bit integer. 836 */ 837 public static int decodeZigZag32(final int n) { 838 return (n >>> 1) ^ -(n & 1); 839 } 840 841 /** 842 * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 843 * into values that can be efficiently encoded with varint. (Otherwise, 844 * negative values must be sign-extended to 64 bits to be varint encoded, 845 * thus always taking 10 bytes on the wire.) 846 * 847 * @param n An unsigned 64-bit integer, stored in a signed int because 848 * Java has no explicit unsigned support. 849 * @return A signed 64-bit integer. 850 */ 851 public static long decodeZigZag64(final long n) { 852 return (n >>> 1) ^ -(n & 1); 853 } 854 855 // ----------------------------------------------------------------- 856 857 private final byte[] buffer; 858 private final boolean bufferIsImmutable; 859 private int bufferSize; 860 private int bufferSizeAfterLimit; 861 private int bufferPos; 862 private final InputStream input; 863 private int lastTag; 864 private boolean enableAliasing = false; 865 866 /** 867 * The total number of bytes read before the current buffer. The total 868 * bytes read up to the current position can be computed as 869 * {@code totalBytesRetired + bufferPos}. This value may be negative if 870 * reading started in the middle of the current buffer (e.g. if the 871 * constructor that takes a byte array and an offset was used). 872 */ 873 private int totalBytesRetired; 874 875 /** The absolute position of the end of the current message. */ 876 private int currentLimit = Integer.MAX_VALUE; 877 878 /** See setRecursionLimit() */ 879 private int recursionDepth; 880 private int recursionLimit = DEFAULT_RECURSION_LIMIT; 881 882 /** See setSizeLimit() */ 883 private int sizeLimit = DEFAULT_SIZE_LIMIT; 884 885 private static final int DEFAULT_RECURSION_LIMIT = 64; 886 private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB 887 private static final int BUFFER_SIZE = 4096; 888 889 private CodedInputStream(final byte[] buffer, final int off, final int len) { 890 this.buffer = buffer; 891 bufferSize = off + len; 892 bufferPos = off; 893 totalBytesRetired = -off; 894 input = null; 895 bufferIsImmutable = false; 896 } 897 898 private CodedInputStream(final InputStream input) { 899 buffer = new byte[BUFFER_SIZE]; 900 bufferSize = 0; 901 bufferPos = 0; 902 totalBytesRetired = 0; 903 this.input = input; 904 bufferIsImmutable = false; 905 } 906 907 private CodedInputStream(final LiteralByteString byteString) { 908 buffer = byteString.bytes; 909 bufferPos = byteString.getOffsetIntoBytes(); 910 bufferSize = bufferPos + byteString.size(); 911 totalBytesRetired = -bufferPos; 912 input = null; 913 bufferIsImmutable = true; 914 } 915 916 public void enableAliasing(boolean enabled) { 917 this.enableAliasing = enabled; 918 } 919 920 /** 921 * Set the maximum message recursion depth. In order to prevent malicious 922 * messages from causing stack overflows, {@code CodedInputStream} limits 923 * how deeply messages may be nested. The default limit is 64. 924 * 925 * @return the old limit. 926 */ 927 public int setRecursionLimit(final int limit) { 928 if (limit < 0) { 929 throw new IllegalArgumentException( 930 "Recursion limit cannot be negative: " + limit); 931 } 932 final int oldLimit = recursionLimit; 933 recursionLimit = limit; 934 return oldLimit; 935 } 936 937 /** 938 * Set the maximum message size. In order to prevent malicious 939 * messages from exhausting memory or causing integer overflows, 940 * {@code CodedInputStream} limits how large a message may be. 941 * The default limit is 64MB. You should set this limit as small 942 * as you can without harming your app's functionality. Note that 943 * size limits only apply when reading from an {@code InputStream}, not 944 * when constructed around a raw byte array (nor with 945 * {@link ByteString#newCodedInput}). 946 * <p> 947 * If you want to read several messages from a single CodedInputStream, you 948 * could call {@link #resetSizeCounter()} after each one to avoid hitting the 949 * size limit. 950 * 951 * @return the old limit. 952 */ 953 public int setSizeLimit(final int limit) { 954 if (limit < 0) { 955 throw new IllegalArgumentException( 956 "Size limit cannot be negative: " + limit); 957 } 958 final int oldLimit = sizeLimit; 959 sizeLimit = limit; 960 return oldLimit; 961 } 962 963 /** 964 * Resets the current size counter to zero (see {@link #setSizeLimit(int)}). 965 */ 966 public void resetSizeCounter() { 967 totalBytesRetired = -bufferPos; 968 } 969 970 /** 971 * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This 972 * is called when descending into a length-delimited embedded message. 973 * 974 * <p>Note that {@code pushLimit()} does NOT affect how many bytes the 975 * {@code CodedInputStream} reads from an underlying {@code InputStream} when 976 * refreshing its buffer. If you need to prevent reading past a certain 977 * point in the underlying {@code InputStream} (e.g. because you expect it to 978 * contain more data after the end of the message which you need to handle 979 * differently) then you must place a wrapper around your {@code InputStream} 980 * which limits the amount of data that can be read from it. 981 * 982 * @return the old limit. 983 */ 984 public int pushLimit(int byteLimit) throws InvalidProtocolBufferException { 985 if (byteLimit < 0) { 986 throw InvalidProtocolBufferException.negativeSize(); 987 } 988 byteLimit += totalBytesRetired + bufferPos; 989 final int oldLimit = currentLimit; 990 if (byteLimit > oldLimit) { 991 throw InvalidProtocolBufferException.truncatedMessage(); 992 } 993 currentLimit = byteLimit; 994 995 recomputeBufferSizeAfterLimit(); 996 997 return oldLimit; 998 } 999 1000 private void recomputeBufferSizeAfterLimit() { 1001 bufferSize += bufferSizeAfterLimit; 1002 final int bufferEnd = totalBytesRetired + bufferSize; 1003 if (bufferEnd > currentLimit) { 1004 // Limit is in current buffer. 1005 bufferSizeAfterLimit = bufferEnd - currentLimit; 1006 bufferSize -= bufferSizeAfterLimit; 1007 } else { 1008 bufferSizeAfterLimit = 0; 1009 } 1010 } 1011 1012 /** 1013 * Discards the current limit, returning to the previous limit. 1014 * 1015 * @param oldLimit The old limit, as returned by {@code pushLimit}. 1016 */ 1017 public void popLimit(final int oldLimit) { 1018 currentLimit = oldLimit; 1019 recomputeBufferSizeAfterLimit(); 1020 } 1021 1022 /** 1023 * Returns the number of bytes to be read before the current limit. 1024 * If no limit is set, returns -1. 1025 */ 1026 public int getBytesUntilLimit() { 1027 if (currentLimit == Integer.MAX_VALUE) { 1028 return -1; 1029 } 1030 1031 final int currentAbsolutePosition = totalBytesRetired + bufferPos; 1032 return currentLimit - currentAbsolutePosition; 1033 } 1034 1035 /** 1036 * Returns true if the stream has reached the end of the input. This is the 1037 * case if either the end of the underlying input source has been reached or 1038 * if the stream has reached a limit created using {@link #pushLimit(int)}. 1039 */ 1040 public boolean isAtEnd() throws IOException { 1041 return bufferPos == bufferSize && !tryRefillBuffer(1); 1042 } 1043 1044 /** 1045 * The total bytes read up to the current position. Calling 1046 * {@link #resetSizeCounter()} resets this value to zero. 1047 */ 1048 public int getTotalBytesRead() { 1049 return totalBytesRetired + bufferPos; 1050 } 1051 1052 private interface RefillCallback { 1053 void onRefill(); 1054 } 1055 1056 private RefillCallback refillCallback = null; 1057 1058 /** 1059 * Ensures that at least {@code n} bytes are available in the buffer, reading 1060 * more bytes from the input if necessary to make it so. Caller must ensure 1061 * that the requested space is less than BUFFER_SIZE. 1062 * 1063 * @throws InvalidProtocolBufferException The end of the stream or the current 1064 * limit was reached. 1065 */ 1066 private void ensureAvailable(int n) throws IOException { 1067 if (bufferSize - bufferPos < n) { 1068 refillBuffer(n); 1069 } 1070 } 1071 1072 /** 1073 * Reads more bytes from the input, making at least {@code n} bytes available 1074 * in the buffer. Caller must ensure that the requested space is not yet 1075 * available, and that the requested space is less than BUFFER_SIZE. 1076 * 1077 * @throws InvalidProtocolBufferException The end of the stream or the current 1078 * limit was reached. 1079 */ 1080 private void refillBuffer(int n) throws IOException { 1081 if (!tryRefillBuffer(n)) { 1082 throw InvalidProtocolBufferException.truncatedMessage(); 1083 } 1084 } 1085 1086 /** 1087 * Tries to read more bytes from the input, making at least {@code n} bytes 1088 * available in the buffer. Caller must ensure that the requested space is 1089 * not yet available, and that the requested space is less than BUFFER_SIZE. 1090 * 1091 * @return {@code true} if the bytes could be made available; {@code false} 1092 * if the end of the stream or the current limit was reached. 1093 */ 1094 private boolean tryRefillBuffer(int n) throws IOException { 1095 if (bufferPos + n <= bufferSize) { 1096 throw new IllegalStateException( 1097 "refillBuffer() called when " + n + 1098 " bytes were already available in buffer"); 1099 } 1100 1101 if (totalBytesRetired + bufferPos + n > currentLimit) { 1102 // Oops, we hit a limit. 1103 return false; 1104 } 1105 1106 if (refillCallback != null) { 1107 refillCallback.onRefill(); 1108 } 1109 1110 if (input != null) { 1111 int pos = bufferPos; 1112 if (pos > 0) { 1113 if (bufferSize > pos) { 1114 System.arraycopy(buffer, pos, buffer, 0, bufferSize - pos); 1115 } 1116 totalBytesRetired += pos; 1117 bufferSize -= pos; 1118 bufferPos = 0; 1119 } 1120 1121 int bytesRead = input.read(buffer, bufferSize, buffer.length - bufferSize); 1122 if (bytesRead == 0 || bytesRead < -1 || bytesRead > buffer.length) { 1123 throw new IllegalStateException( 1124 "InputStream#read(byte[]) returned invalid result: " + bytesRead + 1125 "\nThe InputStream implementation is buggy."); 1126 } 1127 if (bytesRead > 0) { 1128 bufferSize += bytesRead; 1129 // Integer-overflow-conscious check against sizeLimit 1130 if (totalBytesRetired + n - sizeLimit > 0) { 1131 throw InvalidProtocolBufferException.sizeLimitExceeded(); 1132 } 1133 recomputeBufferSizeAfterLimit(); 1134 return (bufferSize >= n) ? true : tryRefillBuffer(n); 1135 } 1136 } 1137 1138 return false; 1139 } 1140 1141 /** 1142 * Read one byte from the input. 1143 * 1144 * @throws InvalidProtocolBufferException The end of the stream or the current 1145 * limit was reached. 1146 */ 1147 public byte readRawByte() throws IOException { 1148 if (bufferPos == bufferSize) { 1149 refillBuffer(1); 1150 } 1151 return buffer[bufferPos++]; 1152 } 1153 1154 /** 1155 * Read a fixed size of bytes from the input. 1156 * 1157 * @throws InvalidProtocolBufferException The end of the stream or the current 1158 * limit was reached. 1159 */ 1160 public byte[] readRawBytes(final int size) throws IOException { 1161 final int pos = bufferPos; 1162 if (size <= (bufferSize - pos) && size > 0) { 1163 bufferPos = pos + size; 1164 return Arrays.copyOfRange(buffer, pos, pos + size); 1165 } else { 1166 return readRawBytesSlowPath(size); 1167 } 1168 } 1169 1170 /** 1171 * Exactly like readRawBytes, but caller must have already checked the fast 1172 * path: (size <= (bufferSize - pos) && size > 0) 1173 */ 1174 private byte[] readRawBytesSlowPath(final int size) throws IOException { 1175 if (size <= 0) { 1176 if (size == 0) { 1177 return Internal.EMPTY_BYTE_ARRAY; 1178 } else { 1179 throw InvalidProtocolBufferException.negativeSize(); 1180 } 1181 } 1182 1183 if (totalBytesRetired + bufferPos + size > currentLimit) { 1184 // Read to the end of the stream anyway. 1185 skipRawBytes(currentLimit - totalBytesRetired - bufferPos); 1186 // Then fail. 1187 throw InvalidProtocolBufferException.truncatedMessage(); 1188 } 1189 1190 if (size < BUFFER_SIZE) { 1191 // Reading more bytes than are in the buffer, but not an excessive number 1192 // of bytes. We can safely allocate the resulting array ahead of time. 1193 1194 // First copy what we have. 1195 final byte[] bytes = new byte[size]; 1196 int pos = bufferSize - bufferPos; 1197 System.arraycopy(buffer, bufferPos, bytes, 0, pos); 1198 bufferPos = bufferSize; 1199 1200 // We want to refill the buffer and then copy from the buffer into our 1201 // byte array rather than reading directly into our byte array because 1202 // the input may be unbuffered. 1203 ensureAvailable(size - pos); 1204 System.arraycopy(buffer, 0, bytes, pos, size - pos); 1205 bufferPos = size - pos; 1206 1207 return bytes; 1208 } else { 1209 // The size is very large. For security reasons, we can't allocate the 1210 // entire byte array yet. The size comes directly from the input, so a 1211 // maliciously-crafted message could provide a bogus very large size in 1212 // order to trick the app into allocating a lot of memory. We avoid this 1213 // by allocating and reading only a small chunk at a time, so that the 1214 // malicious message must actually *be* extremely large to cause 1215 // problems. Meanwhile, we limit the allowed size of a message elsewhere. 1216 1217 // Remember the buffer markers since we'll have to copy the bytes out of 1218 // it later. 1219 final int originalBufferPos = bufferPos; 1220 final int originalBufferSize = bufferSize; 1221 1222 // Mark the current buffer consumed. 1223 totalBytesRetired += bufferSize; 1224 bufferPos = 0; 1225 bufferSize = 0; 1226 1227 // Read all the rest of the bytes we need. 1228 int sizeLeft = size - (originalBufferSize - originalBufferPos); 1229 final List<byte[]> chunks = new ArrayList<byte[]>(); 1230 1231 while (sizeLeft > 0) { 1232 final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)]; 1233 int pos = 0; 1234 while (pos < chunk.length) { 1235 final int n = (input == null) ? -1 : 1236 input.read(chunk, pos, chunk.length - pos); 1237 if (n == -1) { 1238 throw InvalidProtocolBufferException.truncatedMessage(); 1239 } 1240 totalBytesRetired += n; 1241 pos += n; 1242 } 1243 sizeLeft -= chunk.length; 1244 chunks.add(chunk); 1245 } 1246 1247 // OK, got everything. Now concatenate it all into one buffer. 1248 final byte[] bytes = new byte[size]; 1249 1250 // Start by copying the leftover bytes from this.buffer. 1251 int pos = originalBufferSize - originalBufferPos; 1252 System.arraycopy(buffer, originalBufferPos, bytes, 0, pos); 1253 1254 // And now all the chunks. 1255 for (final byte[] chunk : chunks) { 1256 System.arraycopy(chunk, 0, bytes, pos, chunk.length); 1257 pos += chunk.length; 1258 } 1259 1260 // Done. 1261 return bytes; 1262 } 1263 } 1264 1265 /** 1266 * Reads and discards {@code size} bytes. 1267 * 1268 * @throws InvalidProtocolBufferException The end of the stream or the current 1269 * limit was reached. 1270 */ 1271 public void skipRawBytes(final int size) throws IOException { 1272 if (size <= (bufferSize - bufferPos) && size >= 0) { 1273 // We have all the bytes we need already. 1274 bufferPos += size; 1275 } else { 1276 skipRawBytesSlowPath(size); 1277 } 1278 } 1279 1280 /** 1281 * Exactly like skipRawBytes, but caller must have already checked the fast 1282 * path: (size <= (bufferSize - pos) && size >= 0) 1283 */ 1284 private void skipRawBytesSlowPath(final int size) throws IOException { 1285 if (size < 0) { 1286 throw InvalidProtocolBufferException.negativeSize(); 1287 } 1288 1289 if (totalBytesRetired + bufferPos + size > currentLimit) { 1290 // Read to the end of the stream anyway. 1291 skipRawBytes(currentLimit - totalBytesRetired - bufferPos); 1292 // Then fail. 1293 throw InvalidProtocolBufferException.truncatedMessage(); 1294 } 1295 1296 // Skipping more bytes than are in the buffer. First skip what we have. 1297 int pos = bufferSize - bufferPos; 1298 bufferPos = bufferSize; 1299 1300 // Keep refilling the buffer until we get to the point we wanted to skip to. 1301 // This has the side effect of ensuring the limits are updated correctly. 1302 refillBuffer(1); 1303 while (size - pos > bufferSize) { 1304 pos += bufferSize; 1305 bufferPos = bufferSize; 1306 refillBuffer(1); 1307 } 1308 1309 bufferPos = size - pos; 1310 } 1311} 1312