/thirdparty/breakpad/third_party/protobuf/protobuf/java/src/main/java/com/google/protobuf/CodedInputStream.java

http://github.com/tomahawk-player/tomahawk · Java · 885 lines · 500 code · 88 blank · 297 comment · 95 complexity · 86120adb1fdd94852c4b73fbb1ba3431 MD5 · raw file

  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // http://code.google.com/p/protobuf/
  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. package com.google.protobuf;
  31. import java.io.IOException;
  32. import java.io.InputStream;
  33. import java.util.ArrayList;
  34. import java.util.List;
  35. /**
  36. * Reads and decodes protocol message fields.
  37. *
  38. * This class contains two kinds of methods: methods that read specific
  39. * protocol message constructs and field types (e.g. {@link #readTag()} and
  40. * {@link #readInt32()}) and methods that read low-level values (e.g.
  41. * {@link #readRawVarint32()} and {@link #readRawBytes}). If you are reading
  42. * encoded protocol messages, you should use the former methods, but if you are
  43. * reading some other format of your own design, use the latter.
  44. *
  45. * @author kenton@google.com Kenton Varda
  46. */
  47. public final class CodedInputStream {
  48. /**
  49. * Create a new CodedInputStream wrapping the given InputStream.
  50. */
  51. public static CodedInputStream newInstance(final InputStream input) {
  52. return new CodedInputStream(input);
  53. }
  54. /**
  55. * Create a new CodedInputStream wrapping the given byte array.
  56. */
  57. public static CodedInputStream newInstance(final byte[] buf) {
  58. return newInstance(buf, 0, buf.length);
  59. }
  60. /**
  61. * Create a new CodedInputStream wrapping the given byte array slice.
  62. */
  63. public static CodedInputStream newInstance(final byte[] buf, final int off,
  64. final int len) {
  65. CodedInputStream result = new CodedInputStream(buf, off, len);
  66. try {
  67. // Some uses of CodedInputStream can be more efficient if they know
  68. // exactly how many bytes are available. By pushing the end point of the
  69. // buffer as a limit, we allow them to get this information via
  70. // getBytesUntilLimit(). Pushing a limit that we know is at the end of
  71. // the stream can never hurt, since we can never past that point anyway.
  72. result.pushLimit(len);
  73. } catch (InvalidProtocolBufferException ex) {
  74. // The only reason pushLimit() might throw an exception here is if len
  75. // is negative. Normally pushLimit()'s parameter comes directly off the
  76. // wire, so it's important to catch exceptions in case of corrupt or
  77. // malicious data. However, in this case, we expect that len is not a
  78. // user-supplied value, so we can assume that it being negative indicates
  79. // a programming error. Therefore, throwing an unchecked exception is
  80. // appropriate.
  81. throw new IllegalArgumentException(ex);
  82. }
  83. return result;
  84. }
  85. // -----------------------------------------------------------------
  86. /**
  87. * Attempt to read a field tag, returning zero if we have reached EOF.
  88. * Protocol message parsers use this to read tags, since a protocol message
  89. * may legally end wherever a tag occurs, and zero is not a valid tag number.
  90. */
  91. public int readTag() throws IOException {
  92. if (isAtEnd()) {
  93. lastTag = 0;
  94. return 0;
  95. }
  96. lastTag = readRawVarint32();
  97. if (WireFormat.getTagFieldNumber(lastTag) == 0) {
  98. // If we actually read zero (or any tag number corresponding to field
  99. // number zero), that's not a valid tag.
  100. throw InvalidProtocolBufferException.invalidTag();
  101. }
  102. return lastTag;
  103. }
  104. /**
  105. * Verifies that the last call to readTag() returned the given tag value.
  106. * This is used to verify that a nested group ended with the correct
  107. * end tag.
  108. *
  109. * @throws InvalidProtocolBufferException {@code value} does not match the
  110. * last tag.
  111. */
  112. public void checkLastTagWas(final int value)
  113. throws InvalidProtocolBufferException {
  114. if (lastTag != value) {
  115. throw InvalidProtocolBufferException.invalidEndTag();
  116. }
  117. }
  118. /**
  119. * Reads and discards a single field, given its tag value.
  120. *
  121. * @return {@code false} if the tag is an endgroup tag, in which case
  122. * nothing is skipped. Otherwise, returns {@code true}.
  123. */
  124. public boolean skipField(final int tag) throws IOException {
  125. switch (WireFormat.getTagWireType(tag)) {
  126. case WireFormat.WIRETYPE_VARINT:
  127. readInt32();
  128. return true;
  129. case WireFormat.WIRETYPE_FIXED64:
  130. readRawLittleEndian64();
  131. return true;
  132. case WireFormat.WIRETYPE_LENGTH_DELIMITED:
  133. skipRawBytes(readRawVarint32());
  134. return true;
  135. case WireFormat.WIRETYPE_START_GROUP:
  136. skipMessage();
  137. checkLastTagWas(
  138. WireFormat.makeTag(WireFormat.getTagFieldNumber(tag),
  139. WireFormat.WIRETYPE_END_GROUP));
  140. return true;
  141. case WireFormat.WIRETYPE_END_GROUP:
  142. return false;
  143. case WireFormat.WIRETYPE_FIXED32:
  144. readRawLittleEndian32();
  145. return true;
  146. default:
  147. throw InvalidProtocolBufferException.invalidWireType();
  148. }
  149. }
  150. /**
  151. * Reads and discards an entire message. This will read either until EOF
  152. * or until an endgroup tag, whichever comes first.
  153. */
  154. public void skipMessage() throws IOException {
  155. while (true) {
  156. final int tag = readTag();
  157. if (tag == 0 || !skipField(tag)) {
  158. return;
  159. }
  160. }
  161. }
  162. // -----------------------------------------------------------------
  163. /** Read a {@code double} field value from the stream. */
  164. public double readDouble() throws IOException {
  165. return Double.longBitsToDouble(readRawLittleEndian64());
  166. }
  167. /** Read a {@code float} field value from the stream. */
  168. public float readFloat() throws IOException {
  169. return Float.intBitsToFloat(readRawLittleEndian32());
  170. }
  171. /** Read a {@code uint64} field value from the stream. */
  172. public long readUInt64() throws IOException {
  173. return readRawVarint64();
  174. }
  175. /** Read an {@code int64} field value from the stream. */
  176. public long readInt64() throws IOException {
  177. return readRawVarint64();
  178. }
  179. /** Read an {@code int32} field value from the stream. */
  180. public int readInt32() throws IOException {
  181. return readRawVarint32();
  182. }
  183. /** Read a {@code fixed64} field value from the stream. */
  184. public long readFixed64() throws IOException {
  185. return readRawLittleEndian64();
  186. }
  187. /** Read a {@code fixed32} field value from the stream. */
  188. public int readFixed32() throws IOException {
  189. return readRawLittleEndian32();
  190. }
  191. /** Read a {@code bool} field value from the stream. */
  192. public boolean readBool() throws IOException {
  193. return readRawVarint32() != 0;
  194. }
  195. /** Read a {@code string} field value from the stream. */
  196. public String readString() throws IOException {
  197. final int size = readRawVarint32();
  198. if (size <= (bufferSize - bufferPos) && size > 0) {
  199. // Fast path: We already have the bytes in a contiguous buffer, so
  200. // just copy directly from it.
  201. final String result = new String(buffer, bufferPos, size, "UTF-8");
  202. bufferPos += size;
  203. return result;
  204. } else {
  205. // Slow path: Build a byte array first then copy it.
  206. return new String(readRawBytes(size), "UTF-8");
  207. }
  208. }
  209. /** Read a {@code group} field value from the stream. */
  210. public void readGroup(final int fieldNumber,
  211. final MessageLite.Builder builder,
  212. final ExtensionRegistryLite extensionRegistry)
  213. throws IOException {
  214. if (recursionDepth >= recursionLimit) {
  215. throw InvalidProtocolBufferException.recursionLimitExceeded();
  216. }
  217. ++recursionDepth;
  218. builder.mergeFrom(this, extensionRegistry);
  219. checkLastTagWas(
  220. WireFormat.makeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP));
  221. --recursionDepth;
  222. }
  223. /**
  224. * Reads a {@code group} field value from the stream and merges it into the
  225. * given {@link UnknownFieldSet}.
  226. *
  227. * @deprecated UnknownFieldSet.Builder now implements MessageLite.Builder, so
  228. * you can just call {@link #readGroup}.
  229. */
  230. @Deprecated
  231. public void readUnknownGroup(final int fieldNumber,
  232. final MessageLite.Builder builder)
  233. throws IOException {
  234. // We know that UnknownFieldSet will ignore any ExtensionRegistry so it
  235. // is safe to pass null here. (We can't call
  236. // ExtensionRegistry.getEmptyRegistry() because that would make this
  237. // class depend on ExtensionRegistry, which is not part of the lite
  238. // library.)
  239. readGroup(fieldNumber, builder, null);
  240. }
  241. /** Read an embedded message field value from the stream. */
  242. public void readMessage(final MessageLite.Builder builder,
  243. final ExtensionRegistryLite extensionRegistry)
  244. throws IOException {
  245. final int length = readRawVarint32();
  246. if (recursionDepth >= recursionLimit) {
  247. throw InvalidProtocolBufferException.recursionLimitExceeded();
  248. }
  249. final int oldLimit = pushLimit(length);
  250. ++recursionDepth;
  251. builder.mergeFrom(this, extensionRegistry);
  252. checkLastTagWas(0);
  253. --recursionDepth;
  254. popLimit(oldLimit);
  255. }
  256. /** Read a {@code bytes} field value from the stream. */
  257. public ByteString readBytes() throws IOException {
  258. final int size = readRawVarint32();
  259. if (size == 0) {
  260. return ByteString.EMPTY;
  261. } else if (size <= (bufferSize - bufferPos) && size > 0) {
  262. // Fast path: We already have the bytes in a contiguous buffer, so
  263. // just copy directly from it.
  264. final ByteString result = ByteString.copyFrom(buffer, bufferPos, size);
  265. bufferPos += size;
  266. return result;
  267. } else {
  268. // Slow path: Build a byte array first then copy it.
  269. return ByteString.copyFrom(readRawBytes(size));
  270. }
  271. }
  272. /** Read a {@code uint32} field value from the stream. */
  273. public int readUInt32() throws IOException {
  274. return readRawVarint32();
  275. }
  276. /**
  277. * Read an enum field value from the stream. Caller is responsible
  278. * for converting the numeric value to an actual enum.
  279. */
  280. public int readEnum() throws IOException {
  281. return readRawVarint32();
  282. }
  283. /** Read an {@code sfixed32} field value from the stream. */
  284. public int readSFixed32() throws IOException {
  285. return readRawLittleEndian32();
  286. }
  287. /** Read an {@code sfixed64} field value from the stream. */
  288. public long readSFixed64() throws IOException {
  289. return readRawLittleEndian64();
  290. }
  291. /** Read an {@code sint32} field value from the stream. */
  292. public int readSInt32() throws IOException {
  293. return decodeZigZag32(readRawVarint32());
  294. }
  295. /** Read an {@code sint64} field value from the stream. */
  296. public long readSInt64() throws IOException {
  297. return decodeZigZag64(readRawVarint64());
  298. }
  299. // =================================================================
  300. /**
  301. * Read a raw Varint from the stream. If larger than 32 bits, discard the
  302. * upper bits.
  303. */
  304. public int readRawVarint32() throws IOException {
  305. byte tmp = readRawByte();
  306. if (tmp >= 0) {
  307. return tmp;
  308. }
  309. int result = tmp & 0x7f;
  310. if ((tmp = readRawByte()) >= 0) {
  311. result |= tmp << 7;
  312. } else {
  313. result |= (tmp & 0x7f) << 7;
  314. if ((tmp = readRawByte()) >= 0) {
  315. result |= tmp << 14;
  316. } else {
  317. result |= (tmp & 0x7f) << 14;
  318. if ((tmp = readRawByte()) >= 0) {
  319. result |= tmp << 21;
  320. } else {
  321. result |= (tmp & 0x7f) << 21;
  322. result |= (tmp = readRawByte()) << 28;
  323. if (tmp < 0) {
  324. // Discard upper 32 bits.
  325. for (int i = 0; i < 5; i++) {
  326. if (readRawByte() >= 0) {
  327. return result;
  328. }
  329. }
  330. throw InvalidProtocolBufferException.malformedVarint();
  331. }
  332. }
  333. }
  334. }
  335. return result;
  336. }
  337. /**
  338. * Reads a varint from the input one byte at a time, so that it does not
  339. * read any bytes after the end of the varint. If you simply wrapped the
  340. * stream in a CodedInputStream and used {@link #readRawVarint32(InputStream)}
  341. * then you would probably end up reading past the end of the varint since
  342. * CodedInputStream buffers its input.
  343. */
  344. static int readRawVarint32(final InputStream input) throws IOException {
  345. final int firstByte = input.read();
  346. if (firstByte == -1) {
  347. throw InvalidProtocolBufferException.truncatedMessage();
  348. }
  349. return readRawVarint32(firstByte, input);
  350. }
  351. /**
  352. * Like {@link #readRawVarint32(InputStream)}, but expects that the caller
  353. * has already read one byte. This allows the caller to determine if EOF
  354. * has been reached before attempting to read.
  355. */
  356. public static int readRawVarint32(
  357. final int firstByte, final InputStream input) throws IOException {
  358. if ((firstByte & 0x80) == 0) {
  359. return firstByte;
  360. }
  361. int result = firstByte & 0x7f;
  362. int offset = 7;
  363. for (; offset < 32; offset += 7) {
  364. final int b = input.read();
  365. if (b == -1) {
  366. throw InvalidProtocolBufferException.truncatedMessage();
  367. }
  368. result |= (b & 0x7f) << offset;
  369. if ((b & 0x80) == 0) {
  370. return result;
  371. }
  372. }
  373. // Keep reading up to 64 bits.
  374. for (; offset < 64; offset += 7) {
  375. final int b = input.read();
  376. if (b == -1) {
  377. throw InvalidProtocolBufferException.truncatedMessage();
  378. }
  379. if ((b & 0x80) == 0) {
  380. return result;
  381. }
  382. }
  383. throw InvalidProtocolBufferException.malformedVarint();
  384. }
  385. /** Read a raw Varint from the stream. */
  386. public long readRawVarint64() throws IOException {
  387. int shift = 0;
  388. long result = 0;
  389. while (shift < 64) {
  390. final byte b = readRawByte();
  391. result |= (long)(b & 0x7F) << shift;
  392. if ((b & 0x80) == 0) {
  393. return result;
  394. }
  395. shift += 7;
  396. }
  397. throw InvalidProtocolBufferException.malformedVarint();
  398. }
  399. /** Read a 32-bit little-endian integer from the stream. */
  400. public int readRawLittleEndian32() throws IOException {
  401. final byte b1 = readRawByte();
  402. final byte b2 = readRawByte();
  403. final byte b3 = readRawByte();
  404. final byte b4 = readRawByte();
  405. return (((int)b1 & 0xff) ) |
  406. (((int)b2 & 0xff) << 8) |
  407. (((int)b3 & 0xff) << 16) |
  408. (((int)b4 & 0xff) << 24);
  409. }
  410. /** Read a 64-bit little-endian integer from the stream. */
  411. public long readRawLittleEndian64() throws IOException {
  412. final byte b1 = readRawByte();
  413. final byte b2 = readRawByte();
  414. final byte b3 = readRawByte();
  415. final byte b4 = readRawByte();
  416. final byte b5 = readRawByte();
  417. final byte b6 = readRawByte();
  418. final byte b7 = readRawByte();
  419. final byte b8 = readRawByte();
  420. return (((long)b1 & 0xff) ) |
  421. (((long)b2 & 0xff) << 8) |
  422. (((long)b3 & 0xff) << 16) |
  423. (((long)b4 & 0xff) << 24) |
  424. (((long)b5 & 0xff) << 32) |
  425. (((long)b6 & 0xff) << 40) |
  426. (((long)b7 & 0xff) << 48) |
  427. (((long)b8 & 0xff) << 56);
  428. }
  429. /**
  430. * Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
  431. * into values that can be efficiently encoded with varint. (Otherwise,
  432. * negative values must be sign-extended to 64 bits to be varint encoded,
  433. * thus always taking 10 bytes on the wire.)
  434. *
  435. * @param n An unsigned 32-bit integer, stored in a signed int because
  436. * Java has no explicit unsigned support.
  437. * @return A signed 32-bit integer.
  438. */
  439. public static int decodeZigZag32(final int n) {
  440. return (n >>> 1) ^ -(n & 1);
  441. }
  442. /**
  443. * Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
  444. * into values that can be efficiently encoded with varint. (Otherwise,
  445. * negative values must be sign-extended to 64 bits to be varint encoded,
  446. * thus always taking 10 bytes on the wire.)
  447. *
  448. * @param n An unsigned 64-bit integer, stored in a signed int because
  449. * Java has no explicit unsigned support.
  450. * @return A signed 64-bit integer.
  451. */
  452. public static long decodeZigZag64(final long n) {
  453. return (n >>> 1) ^ -(n & 1);
  454. }
  455. // -----------------------------------------------------------------
  456. private final byte[] buffer;
  457. private int bufferSize;
  458. private int bufferSizeAfterLimit;
  459. private int bufferPos;
  460. private final InputStream input;
  461. private int lastTag;
  462. /**
  463. * The total number of bytes read before the current buffer. The total
  464. * bytes read up to the current position can be computed as
  465. * {@code totalBytesRetired + bufferPos}. This value may be negative if
  466. * reading started in the middle of the current buffer (e.g. if the
  467. * constructor that takes a byte array and an offset was used).
  468. */
  469. private int totalBytesRetired;
  470. /** The absolute position of the end of the current message. */
  471. private int currentLimit = Integer.MAX_VALUE;
  472. /** See setRecursionLimit() */
  473. private int recursionDepth;
  474. private int recursionLimit = DEFAULT_RECURSION_LIMIT;
  475. /** See setSizeLimit() */
  476. private int sizeLimit = DEFAULT_SIZE_LIMIT;
  477. private static final int DEFAULT_RECURSION_LIMIT = 64;
  478. private static final int DEFAULT_SIZE_LIMIT = 64 << 20; // 64MB
  479. private static final int BUFFER_SIZE = 4096;
  480. private CodedInputStream(final byte[] buffer, final int off, final int len) {
  481. this.buffer = buffer;
  482. bufferSize = off + len;
  483. bufferPos = off;
  484. totalBytesRetired = -off;
  485. input = null;
  486. }
  487. private CodedInputStream(final InputStream input) {
  488. buffer = new byte[BUFFER_SIZE];
  489. bufferSize = 0;
  490. bufferPos = 0;
  491. totalBytesRetired = 0;
  492. this.input = input;
  493. }
  494. /**
  495. * Set the maximum message recursion depth. In order to prevent malicious
  496. * messages from causing stack overflows, {@code CodedInputStream} limits
  497. * how deeply messages may be nested. The default limit is 64.
  498. *
  499. * @return the old limit.
  500. */
  501. public int setRecursionLimit(final int limit) {
  502. if (limit < 0) {
  503. throw new IllegalArgumentException(
  504. "Recursion limit cannot be negative: " + limit);
  505. }
  506. final int oldLimit = recursionLimit;
  507. recursionLimit = limit;
  508. return oldLimit;
  509. }
  510. /**
  511. * Set the maximum message size. In order to prevent malicious
  512. * messages from exhausting memory or causing integer overflows,
  513. * {@code CodedInputStream} limits how large a message may be.
  514. * The default limit is 64MB. You should set this limit as small
  515. * as you can without harming your app's functionality. Note that
  516. * size limits only apply when reading from an {@code InputStream}, not
  517. * when constructed around a raw byte array (nor with
  518. * {@link ByteString#newCodedInput}).
  519. * <p>
  520. * If you want to read several messages from a single CodedInputStream, you
  521. * could call {@link #resetSizeCounter()} after each one to avoid hitting the
  522. * size limit.
  523. *
  524. * @return the old limit.
  525. */
  526. public int setSizeLimit(final int limit) {
  527. if (limit < 0) {
  528. throw new IllegalArgumentException(
  529. "Size limit cannot be negative: " + limit);
  530. }
  531. final int oldLimit = sizeLimit;
  532. sizeLimit = limit;
  533. return oldLimit;
  534. }
  535. /**
  536. * Resets the current size counter to zero (see {@link #setSizeLimit(int)}).
  537. */
  538. public void resetSizeCounter() {
  539. totalBytesRetired = -bufferPos;
  540. }
  541. /**
  542. * Sets {@code currentLimit} to (current position) + {@code byteLimit}. This
  543. * is called when descending into a length-delimited embedded message.
  544. *
  545. * <p>Note that {@code pushLimit()} does NOT affect how many bytes the
  546. * {@code CodedInputStream} reads from an underlying {@code InputStream} when
  547. * refreshing its buffer. If you need to prevent reading past a certain
  548. * point in the underlying {@code InputStream} (e.g. because you expect it to
  549. * contain more data after the end of the message which you need to handle
  550. * differently) then you must place a wrapper around you {@code InputStream}
  551. * which limits the amount of data that can be read from it.
  552. *
  553. * @return the old limit.
  554. */
  555. public int pushLimit(int byteLimit) throws InvalidProtocolBufferException {
  556. if (byteLimit < 0) {
  557. throw InvalidProtocolBufferException.negativeSize();
  558. }
  559. byteLimit += totalBytesRetired + bufferPos;
  560. final int oldLimit = currentLimit;
  561. if (byteLimit > oldLimit) {
  562. throw InvalidProtocolBufferException.truncatedMessage();
  563. }
  564. currentLimit = byteLimit;
  565. recomputeBufferSizeAfterLimit();
  566. return oldLimit;
  567. }
  568. private void recomputeBufferSizeAfterLimit() {
  569. bufferSize += bufferSizeAfterLimit;
  570. final int bufferEnd = totalBytesRetired + bufferSize;
  571. if (bufferEnd > currentLimit) {
  572. // Limit is in current buffer.
  573. bufferSizeAfterLimit = bufferEnd - currentLimit;
  574. bufferSize -= bufferSizeAfterLimit;
  575. } else {
  576. bufferSizeAfterLimit = 0;
  577. }
  578. }
  579. /**
  580. * Discards the current limit, returning to the previous limit.
  581. *
  582. * @param oldLimit The old limit, as returned by {@code pushLimit}.
  583. */
  584. public void popLimit(final int oldLimit) {
  585. currentLimit = oldLimit;
  586. recomputeBufferSizeAfterLimit();
  587. }
  588. /**
  589. * Returns the number of bytes to be read before the current limit.
  590. * If no limit is set, returns -1.
  591. */
  592. public int getBytesUntilLimit() {
  593. if (currentLimit == Integer.MAX_VALUE) {
  594. return -1;
  595. }
  596. final int currentAbsolutePosition = totalBytesRetired + bufferPos;
  597. return currentLimit - currentAbsolutePosition;
  598. }
  599. /**
  600. * Returns true if the stream has reached the end of the input. This is the
  601. * case if either the end of the underlying input source has been reached or
  602. * if the stream has reached a limit created using {@link #pushLimit(int)}.
  603. */
  604. public boolean isAtEnd() throws IOException {
  605. return bufferPos == bufferSize && !refillBuffer(false);
  606. }
  607. /**
  608. * The total bytes read up to the current position. Calling
  609. * {@link #resetSizeCounter()} resets this value to zero.
  610. */
  611. public int getTotalBytesRead() {
  612. return totalBytesRetired + bufferPos;
  613. }
  614. /**
  615. * Called with {@code this.buffer} is empty to read more bytes from the
  616. * input. If {@code mustSucceed} is true, refillBuffer() gurantees that
  617. * either there will be at least one byte in the buffer when it returns
  618. * or it will throw an exception. If {@code mustSucceed} is false,
  619. * refillBuffer() returns false if no more bytes were available.
  620. */
  621. private boolean refillBuffer(final boolean mustSucceed) throws IOException {
  622. if (bufferPos < bufferSize) {
  623. throw new IllegalStateException(
  624. "refillBuffer() called when buffer wasn't empty.");
  625. }
  626. if (totalBytesRetired + bufferSize == currentLimit) {
  627. // Oops, we hit a limit.
  628. if (mustSucceed) {
  629. throw InvalidProtocolBufferException.truncatedMessage();
  630. } else {
  631. return false;
  632. }
  633. }
  634. totalBytesRetired += bufferSize;
  635. bufferPos = 0;
  636. bufferSize = (input == null) ? -1 : input.read(buffer);
  637. if (bufferSize == 0 || bufferSize < -1) {
  638. throw new IllegalStateException(
  639. "InputStream#read(byte[]) returned invalid result: " + bufferSize +
  640. "\nThe InputStream implementation is buggy.");
  641. }
  642. if (bufferSize == -1) {
  643. bufferSize = 0;
  644. if (mustSucceed) {
  645. throw InvalidProtocolBufferException.truncatedMessage();
  646. } else {
  647. return false;
  648. }
  649. } else {
  650. recomputeBufferSizeAfterLimit();
  651. final int totalBytesRead =
  652. totalBytesRetired + bufferSize + bufferSizeAfterLimit;
  653. if (totalBytesRead > sizeLimit || totalBytesRead < 0) {
  654. throw InvalidProtocolBufferException.sizeLimitExceeded();
  655. }
  656. return true;
  657. }
  658. }
  659. /**
  660. * Read one byte from the input.
  661. *
  662. * @throws InvalidProtocolBufferException The end of the stream or the current
  663. * limit was reached.
  664. */
  665. public byte readRawByte() throws IOException {
  666. if (bufferPos == bufferSize) {
  667. refillBuffer(true);
  668. }
  669. return buffer[bufferPos++];
  670. }
  671. /**
  672. * Read a fixed size of bytes from the input.
  673. *
  674. * @throws InvalidProtocolBufferException The end of the stream or the current
  675. * limit was reached.
  676. */
  677. public byte[] readRawBytes(final int size) throws IOException {
  678. if (size < 0) {
  679. throw InvalidProtocolBufferException.negativeSize();
  680. }
  681. if (totalBytesRetired + bufferPos + size > currentLimit) {
  682. // Read to the end of the stream anyway.
  683. skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  684. // Then fail.
  685. throw InvalidProtocolBufferException.truncatedMessage();
  686. }
  687. if (size <= bufferSize - bufferPos) {
  688. // We have all the bytes we need already.
  689. final byte[] bytes = new byte[size];
  690. System.arraycopy(buffer, bufferPos, bytes, 0, size);
  691. bufferPos += size;
  692. return bytes;
  693. } else if (size < BUFFER_SIZE) {
  694. // Reading more bytes than are in the buffer, but not an excessive number
  695. // of bytes. We can safely allocate the resulting array ahead of time.
  696. // First copy what we have.
  697. final byte[] bytes = new byte[size];
  698. int pos = bufferSize - bufferPos;
  699. System.arraycopy(buffer, bufferPos, bytes, 0, pos);
  700. bufferPos = bufferSize;
  701. // We want to use refillBuffer() and then copy from the buffer into our
  702. // byte array rather than reading directly into our byte array because
  703. // the input may be unbuffered.
  704. refillBuffer(true);
  705. while (size - pos > bufferSize) {
  706. System.arraycopy(buffer, 0, bytes, pos, bufferSize);
  707. pos += bufferSize;
  708. bufferPos = bufferSize;
  709. refillBuffer(true);
  710. }
  711. System.arraycopy(buffer, 0, bytes, pos, size - pos);
  712. bufferPos = size - pos;
  713. return bytes;
  714. } else {
  715. // The size is very large. For security reasons, we can't allocate the
  716. // entire byte array yet. The size comes directly from the input, so a
  717. // maliciously-crafted message could provide a bogus very large size in
  718. // order to trick the app into allocating a lot of memory. We avoid this
  719. // by allocating and reading only a small chunk at a time, so that the
  720. // malicious message must actually *be* extremely large to cause
  721. // problems. Meanwhile, we limit the allowed size of a message elsewhere.
  722. // Remember the buffer markers since we'll have to copy the bytes out of
  723. // it later.
  724. final int originalBufferPos = bufferPos;
  725. final int originalBufferSize = bufferSize;
  726. // Mark the current buffer consumed.
  727. totalBytesRetired += bufferSize;
  728. bufferPos = 0;
  729. bufferSize = 0;
  730. // Read all the rest of the bytes we need.
  731. int sizeLeft = size - (originalBufferSize - originalBufferPos);
  732. final List<byte[]> chunks = new ArrayList<byte[]>();
  733. while (sizeLeft > 0) {
  734. final byte[] chunk = new byte[Math.min(sizeLeft, BUFFER_SIZE)];
  735. int pos = 0;
  736. while (pos < chunk.length) {
  737. final int n = (input == null) ? -1 :
  738. input.read(chunk, pos, chunk.length - pos);
  739. if (n == -1) {
  740. throw InvalidProtocolBufferException.truncatedMessage();
  741. }
  742. totalBytesRetired += n;
  743. pos += n;
  744. }
  745. sizeLeft -= chunk.length;
  746. chunks.add(chunk);
  747. }
  748. // OK, got everything. Now concatenate it all into one buffer.
  749. final byte[] bytes = new byte[size];
  750. // Start by copying the leftover bytes from this.buffer.
  751. int pos = originalBufferSize - originalBufferPos;
  752. System.arraycopy(buffer, originalBufferPos, bytes, 0, pos);
  753. // And now all the chunks.
  754. for (final byte[] chunk : chunks) {
  755. System.arraycopy(chunk, 0, bytes, pos, chunk.length);
  756. pos += chunk.length;
  757. }
  758. // Done.
  759. return bytes;
  760. }
  761. }
  762. /**
  763. * Reads and discards {@code size} bytes.
  764. *
  765. * @throws InvalidProtocolBufferException The end of the stream or the current
  766. * limit was reached.
  767. */
  768. public void skipRawBytes(final int size) throws IOException {
  769. if (size < 0) {
  770. throw InvalidProtocolBufferException.negativeSize();
  771. }
  772. if (totalBytesRetired + bufferPos + size > currentLimit) {
  773. // Read to the end of the stream anyway.
  774. skipRawBytes(currentLimit - totalBytesRetired - bufferPos);
  775. // Then fail.
  776. throw InvalidProtocolBufferException.truncatedMessage();
  777. }
  778. if (size <= bufferSize - bufferPos) {
  779. // We have all the bytes we need already.
  780. bufferPos += size;
  781. } else {
  782. // Skipping more bytes than are in the buffer. First skip what we have.
  783. int pos = bufferSize - bufferPos;
  784. bufferPos = bufferSize;
  785. // Keep refilling the buffer until we get to the point we wanted to skip
  786. // to. This has the side effect of ensuring the limits are updated
  787. // correctly.
  788. refillBuffer(true);
  789. while (size - pos > bufferSize) {
  790. pos += bufferSize;
  791. bufferPos = bufferSize;
  792. refillBuffer(true);
  793. }
  794. bufferPos = size - pos;
  795. }
  796. }
  797. }