public void ReadStringGreaterThanCurrentLimit()
        {
            MemoryStream      ms     = new MemoryStream();
            CodedOutputStream output = new CodedOutputStream(ms);
            uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited);

            output.WriteRawVarint32(tag);
            output.WriteRawVarint32(4);
            output.WriteRawBytes(new byte[4]); // Pad with a few random bytes.
            output.Flush();
            ms.Position = 0;

            CodedInputStream input = new CodedInputStream(ms.ToArray());

            Assert.AreEqual(tag, input.ReadTag());

            // Specify limit smaller than data length
            input.PushLimit(3);
            Assert.Throws <InvalidProtocolBufferException>(() => input.ReadString());

            AssertReadFromParseContext(new ReadOnlySequence <byte>(ms.ToArray()), (ref ParseContext ctx) =>
            {
                Assert.AreEqual(tag, ctx.ReadTag());
                SegmentedBufferHelper.PushLimit(ref ctx.state, 3);
                try
                {
                    ctx.ReadString();
                    Assert.Fail();
                }
                catch (InvalidProtocolBufferException) { }
            }, true);
        }
        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);
        }
Exemple #3
0
            internal static T Read <T>(ref ParseContext ctx, FieldCodec <T> codec)
            {
                int length   = ctx.ReadLength();
                int oldLimit = SegmentedBufferHelper.PushLimit(ref ctx.state, length);

                uint tag;
                T    value = codec.DefaultValue;

                while ((tag = ctx.ReadTag()) != 0)
                {
                    if (tag == codec.Tag)
                    {
                        value = codec.Read(ref ctx);
                    }
                    else
                    {
                        ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
                    }
                }
                ParsingPrimitivesMessages.CheckReadEndOfStreamTag(ref ctx.state);
                SegmentedBufferHelper.PopLimit(ref ctx.state, oldLimit);

                return(value);
            }
 /// <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>
 internal int PushLimit(int byteLimit)
 {
     return(SegmentedBufferHelper.PushLimit(ref state, byteLimit));
 }
        public static KeyValuePair <TKey, TValue> ReadMapEntry <TKey, TValue>(ref ParseContext ctx, MapField <TKey, TValue> .Codec codec)
        {
            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;

            TKey   key   = codec.KeyCodec.DefaultValue;
            TValue value = codec.ValueCodec.DefaultValue;

            uint tag;

            while ((tag = ctx.ReadTag()) != 0)
            {
                if (tag == codec.KeyCodec.Tag)
                {
                    key = codec.KeyCodec.Read(ref ctx);
                }
                else if (tag == codec.ValueCodec.Tag)
                {
                    value = codec.ValueCodec.Read(ref ctx);
                }
                else
                {
                    SkipLastField(ref ctx.buffer, ref ctx.state);
                }
            }

            // Corner case: a map entry with a key but no value, where the value type is a message.
            // Read it as if we'd seen input with no data (i.e. create a "default" message).
            if (value == null)
            {
                if (ctx.state.CodedInputStream != null)
                {
                    // the decoded message might not support parsing from ParseContext, so
                    // we need to allow fallback to the legacy MergeFrom(CodedInputStream) parsing.
                    value = codec.ValueCodec.Read(new CodedInputStream(ZeroLengthMessageStreamData));
                }
                else
                {
                    ParseContext.Initialize(new ReadOnlySequence <byte>(ZeroLengthMessageStreamData), out ParseContext zeroLengthCtx);
                    value = codec.ValueCodec.Read(ref zeroLengthCtx);
                }
            }

            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);

            return(new KeyValuePair <TKey, TValue>(key, value));
        }