|
|
|
@ -177,6 +177,7 @@ public abstract class CodedInputStream { |
|
|
|
|
throw InvalidProtocolBufferException.recursionLimitExceeded(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Disable construction/inheritance outside of this class. */ |
|
|
|
|
private CodedInputStream() {} |
|
|
|
|
|
|
|
|
@ -2005,6 +2006,7 @@ public abstract class CodedInputStream { |
|
|
|
|
private static final class StreamDecoder extends CodedInputStream { |
|
|
|
|
private final InputStream input; |
|
|
|
|
private final byte[] buffer; |
|
|
|
|
|
|
|
|
|
/** bufferSize represents how many bytes are currently filled in the buffer */ |
|
|
|
|
private int bufferSize; |
|
|
|
|
|
|
|
|
@ -2426,7 +2428,7 @@ public abstract class CodedInputStream { |
|
|
|
|
return Internal.EMPTY_BYTE_BUFFER; |
|
|
|
|
} |
|
|
|
|
// Slow path: Build a byte array first then copy it.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We must copy as the byte array was handed off to the InputStream and a malicious
|
|
|
|
|
// implementation could retain a reference.
|
|
|
|
|
return ByteBuffer.wrap(readRawBytesSlowPath(size, /* ensureNoLeakedReferences= */ true)); |
|
|
|
@ -2841,12 +2843,12 @@ public abstract class CodedInputStream { |
|
|
|
|
/** |
|
|
|
|
* Exactly like readRawBytes, but caller must have already checked the fast path: (size <= |
|
|
|
|
* (bufferSize - pos) && size > 0) |
|
|
|
|
* |
|
|
|
|
* If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to |
|
|
|
|
* |
|
|
|
|
* <p>If ensureNoLeakedReferences is true, the value is guaranteed to have not escaped to |
|
|
|
|
* untrusted code. |
|
|
|
|
*/ |
|
|
|
|
private byte[] readRawBytesSlowPath( |
|
|
|
|
final int size, boolean ensureNoLeakedReferences) throws IOException { |
|
|
|
|
private byte[] readRawBytesSlowPath(final int size, boolean ensureNoLeakedReferences) |
|
|
|
|
throws IOException { |
|
|
|
|
// Attempt to read the data in one byte array when it's safe to do.
|
|
|
|
|
byte[] result = readRawBytesSlowPathOneChunk(size); |
|
|
|
|
if (result != null) { |
|
|
|
@ -2946,8 +2948,8 @@ public abstract class CodedInputStream { |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Reads the remaining data in small chunks from the input stream. |
|
|
|
|
* |
|
|
|
|
* Returns a byte[] that may have escaped to user code via InputStream APIs. |
|
|
|
|
* |
|
|
|
|
* <p>Returns a byte[] that may have escaped to user code via InputStream APIs. |
|
|
|
|
*/ |
|
|
|
|
private List<byte[]> readRawBytesSlowPathRemainingChunks(int sizeLeft) throws IOException { |
|
|
|
|
// The size is very large. For security reasons, we can't allocate the
|
|
|
|
@ -3017,7 +3019,7 @@ public abstract class CodedInputStream { |
|
|
|
|
System.arraycopy(chunk, 0, bytes, tempPos, chunk.length); |
|
|
|
|
tempPos += chunk.length; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ByteString.wrap(bytes); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -3105,41 +3107,54 @@ public abstract class CodedInputStream { |
|
|
|
|
private static final class IterableDirectByteBufferDecoder extends CodedInputStream { |
|
|
|
|
/** The object that need to decode. */ |
|
|
|
|
private final Iterable<ByteBuffer> input; |
|
|
|
|
|
|
|
|
|
/** The {@link Iterator} with type {@link ByteBuffer} of {@code input} */ |
|
|
|
|
private final Iterator<ByteBuffer> iterator; |
|
|
|
|
|
|
|
|
|
/** The current ByteBuffer; */ |
|
|
|
|
private ByteBuffer currentByteBuffer; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* If {@code true}, indicates that all the buffers are backing a {@link ByteString} and are |
|
|
|
|
* therefore considered to be an immutable input source. |
|
|
|
|
*/ |
|
|
|
|
private final boolean immutable; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* If {@code true}, indicates that calls to read {@link ByteString} or {@code byte[]} |
|
|
|
|
* <strong>may</strong> return slices of the underlying buffer, rather than copies. |
|
|
|
|
*/ |
|
|
|
|
private boolean enableAliasing; |
|
|
|
|
|
|
|
|
|
/** The global total message length limit */ |
|
|
|
|
private int totalBufferSize; |
|
|
|
|
|
|
|
|
|
/** The amount of available data in the input beyond {@link #currentLimit}. */ |
|
|
|
|
private int bufferSizeAfterCurrentLimit; |
|
|
|
|
|
|
|
|
|
/** The absolute position of the end of the current message. */ |
|
|
|
|
private int currentLimit = Integer.MAX_VALUE; |
|
|
|
|
|
|
|
|
|
/** The last tag that was read from this stream. */ |
|
|
|
|
private int lastTag; |
|
|
|
|
|
|
|
|
|
/** Total Bytes have been Read from the {@link Iterable} {@link ByteBuffer} */ |
|
|
|
|
private int totalBytesRead; |
|
|
|
|
|
|
|
|
|
/** The start position offset of the whole message, used as to reset the totalBytesRead */ |
|
|
|
|
private int startOffset; |
|
|
|
|
|
|
|
|
|
/** The current position for current ByteBuffer */ |
|
|
|
|
private long currentByteBufferPos; |
|
|
|
|
|
|
|
|
|
private long currentByteBufferStartPos; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* If the current ByteBuffer is unsafe-direct based, currentAddress is the start address of this |
|
|
|
|
* ByteBuffer; otherwise should be zero. |
|
|
|
|
*/ |
|
|
|
|
private long currentAddress; |
|
|
|
|
|
|
|
|
|
/** The limit position for current ByteBuffer */ |
|
|
|
|
private long currentByteBufferLimit; |
|
|
|
|
|
|
|
|
|