private static uint ParseRawVarint32SlowPath(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { int tmp = ReadRawByte(ref buffer, ref state); if (tmp < 128) { return((uint)tmp); } int result = tmp & 0x7f; if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) { result |= tmp << 7; } else { result |= (tmp & 0x7f) << 7; if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) { result |= tmp << 14; } else { result |= (tmp & 0x7f) << 14; if ((tmp = ReadRawByte(ref buffer, ref state)) < 128) { result |= tmp << 21; } else { result |= (tmp & 0x7f) << 21; result |= (tmp = ReadRawByte(ref buffer, ref state)) << 28; if (tmp >= 128) { // Discard upper 32 bits. for (int i = 0; i < 5; i++) { if (ReadRawByte(ref buffer, ref state) < 128) { return((uint)result); } } throw InvalidProtocolBufferException.MalformedVarint(); } } } } return((uint)result); }
public static void ReadGroup(ref ParseContext ctx, IMessage message) { if (ctx.state.recursionDepth >= ctx.state.recursionLimit) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } ++ctx.state.recursionDepth; uint tag = ctx.state.lastTag; int fieldNumber = WireFormat.GetTagFieldNumber(tag); ReadRawMessage(ref ctx, message); CheckLastTagWas(ref ctx.state, WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); --ctx.state.recursionDepth; }
/// <summary> /// Reads a fixed size of bytes from the input. /// </summary> /// <exception cref="InvalidProtocolBufferException"> /// the end of the stream or the current limit was reached /// </exception> public static byte[] ReadRawBytes(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state, int size) { if (size < 0) { throw InvalidProtocolBufferException.NegativeSize(); } if (size <= state.bufferSize - state.bufferPos) { // We have all the bytes we need already. byte[] bytes = new byte[size]; buffer.Slice(state.bufferPos, size).CopyTo(bytes); state.bufferPos += size; return(bytes); } return(ReadRawBytesSlow(ref buffer, ref state, size)); }
private static ulong ParseRawVarint64SlowPath(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state) { int shift = 0; ulong result = 0; do { byte b = ReadRawByte(ref buffer, ref state); result |= (ulong)(b & 0x7F) << shift; if (b < 0x80) { return(result); } shift += 7; }while (shift < 64); throw InvalidProtocolBufferException.MalformedVarint(); }
/// <summary> /// Sets currentLimit to (current position) + byteLimit. This is called /// when descending into a length-delimited embedded message. The previous /// limit is returned. /// </summary> /// <returns>The old limit.</returns> public static int PushLimit(ref ParserInternalState state, int byteLimit) { if (byteLimit < 0) { throw InvalidProtocolBufferException.NegativeSize(); } byteLimit += state.totalBytesRetired + state.bufferPos; int oldLimit = state.currentLimit; if (byteLimit > oldLimit) { throw InvalidProtocolBufferException.TruncatedMessage(); } state.currentLimit = byteLimit; RecomputeBufferSizeAfterLimit(ref state); return(oldLimit); }
public static void ReadMessage(ref ParseContext ctx, IMessage message) { int length = ParsingPrimitives.ParseLength(ref ctx.buffer, ref ctx.state); if (ctx.state.recursionDepth >= ctx.state.recursionLimit) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length); ++ctx.state.recursionDepth; ReadRawMessage(ref ctx, message); CheckReadEndOfStreamTag(ref ctx.state); // Check that we've read exactly as much data as expected. if (!SegmentedBufferHelper.IsReachedLimit(ref ctx.state)) { throw InvalidProtocolBufferException.TruncatedMessage(); } --ctx.state.recursionDepth; SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit); }
/// <summary> /// Skip a group. /// </summary> public static void SkipGroup(ref ReadOnlySpan <byte> buffer, ref ParserInternalState state, uint startGroupTag) { // Note: Currently we expect this to be the way that groups are read. We could put the recursion // depth changes into the ReadTag method instead, potentially... state.recursionDepth++; if (state.recursionDepth >= state.recursionLimit) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } uint tag; while (true) { tag = ParsingPrimitives.ParseTag(ref buffer, ref state); if (tag == 0) { throw InvalidProtocolBufferException.TruncatedMessage(); } // Can't call SkipLastField for this case- that would throw. if (WireFormat.GetTagWireType(tag) == WireFormat.WireType.EndGroup) { break; } // This recursion will allow us to handle nested groups. SkipLastField(ref buffer, ref state); } int startField = WireFormat.GetTagFieldNumber(startGroupTag); int endField = WireFormat.GetTagFieldNumber(tag); if (startField != endField) { throw new InvalidProtocolBufferException( $"Mismatched end-group tag. Started with field {startField}; ended with field {endField}"); } state.recursionDepth--; }