Example #1
0
        /// <summary>
        /// Same code as ReadRawVarint32, but read each byte individually, checking for
        /// buffer overflow.
        /// </summary>
        private uint SlowReadRawVarint32()
        {
            int tmp = ReadRawByte();

            if (tmp < 128)
            {
                return((uint)tmp);
            }
            int result = tmp & 0x7f;

            if ((tmp = ReadRawByte()) < 128)
            {
                result |= tmp << 7;
            }
            else
            {
                result |= (tmp & 0x7f) << 7;
                if ((tmp = ReadRawByte()) < 128)
                {
                    result |= tmp << 14;
                }
                else
                {
                    result |= (tmp & 0x7f) << 14;
                    if ((tmp = ReadRawByte()) < 128)
                    {
                        result |= tmp << 21;
                    }
                    else
                    {
                        result |= (tmp & 0x7f) << 21;
                        result |= (tmp = ReadRawByte()) << 28;
                        if (tmp >= 128)
                        {
                            // Discard upper 32 bits.
                            for (int i = 0; i < 5; i++)
                            {
                                if (ReadRawByte() < 128)
                                {
                                    return((uint)result);
                                }
                            }
                            throw InvalidProtocolBufferException.MalformedVarint();
                        }
                    }
                }
            }
            return((uint)result);
        }
Example #2
0
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            var exception          = Assert.Throws <InvalidProtocolBufferException>(() => input.ReadRawVarint32());

            Assert.AreEqual(expected.Message, exception.Message);

            input     = CodedInputStream.CreateInstance(data);
            exception = Assert.Throws <InvalidProtocolBufferException>(() => input.ReadRawVarint64());
            Assert.AreEqual(expected.Message, exception.Message);

            // Make sure we get the same error when reading directly from a Stream.
            exception = Assert.Throws <InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));
            Assert.AreEqual(expected.Message, exception.Message);
        }
 public IEnumerator <TMessage> GetEnumerator()
 {
     using (Stream stream = streamProvider()) {
         CodedInputStream input = CodedInputStream.CreateInstance(stream);
         uint             tag;
         while ((tag = input.ReadTag()) != 0)
         {
             if (tag != ExpectedTag)
             {
                 throw InvalidProtocolBufferException.InvalidMessageStreamTag();
             }
             yield return(messageReader(input, extensionRegistry));
         }
     }
 }
        private uint SlowReadRawVarint32()
        {
            int num = (int)this.ReadRawByte();

            if (num < 128)
            {
                return((uint)num);
            }
            int num2 = num & 127;

            if ((num = (int)this.ReadRawByte()) < 128)
            {
                num2 |= num << 7;
            }
            else
            {
                num2 |= (num & 127) << 7;
                if ((num = (int)this.ReadRawByte()) < 128)
                {
                    num2 |= num << 14;
                }
                else
                {
                    num2 |= (num & 127) << 14;
                    if ((num = (int)this.ReadRawByte()) < 128)
                    {
                        num2 |= num << 21;
                    }
                    else
                    {
                        num2 |= (num & 127) << 21;
                        num2 |= (num = (int)this.ReadRawByte()) << 28;
                        if (num >= 128)
                        {
                            for (int i = 0; i < 5; i++)
                            {
                                if (this.ReadRawByte() < 128)
                                {
                                    return((uint)num2);
                                }
                            }
                            throw InvalidProtocolBufferException.MalformedVarint();
                        }
                    }
                }
            }
            return((uint)num2);
        }
Example #5
0
        /// <summary>
        /// Attempt to read a field tag, returning 0 if we have reached the end
        /// of the input data. Protocol message parsers use this to read tags,
        /// since a protocol message may legally end wherever a tag occurs, and
        /// zero is not a valid tag number.
        /// </summary>
        public uint ReadTag()
        {
            if (bufferPos == bufferSize && !RefillBuffer(false))
            {
                lastTag = 0;
                return(0);
            }

            lastTag = ReadRawVarint32();
            if (lastTag == 0)
            {
                // If we actually read zero, that's not a valid tag.
                throw InvalidProtocolBufferException.InvalidTag();
            }
            return(lastTag);
        }
        public void ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
        {
            int byteLimit = (int)this.ReadRawVarint32();

            if (this.recursionDepth >= this.recursionLimit)
            {
                throw InvalidProtocolBufferException.RecursionLimitExceeded();
            }
            int oldLimit = this.PushLimit(byteLimit);

            this.recursionDepth++;
            builder.WeakMergeFrom(this, extensionRegistry);
            this.CheckLastTagWas(0u);
            this.recursionDepth--;
            this.PopLimit(oldLimit);
        }
        /// <summary>
        /// Attempt to read a field tag, returning 0 if we have reached the end
        /// of the input data. Protocol message parsers use this to read tags,
        /// since a protocol message may legally end wherever a tag occurs, and
        /// zero is not a valid tag number.
        /// </summary>

        public uint ReadTag()
        {
            if (IsAtEnd)
            {
                lastTag = 0;
                return(0);
            }

            lastTag = ReadRawVarint32();
            if (lastTag == 0)
            {
                // If we actually read zero, that's not a valid tag.
                throw InvalidProtocolBufferException.InvalidTag();
            }
            return(lastTag);
        }
        /// <summary>
        /// Reads a group field value from the stream.
        /// </summary>

        /*ZWL
         * public void ReadGroup(int fieldNumber, IBuilderLite builder,
         *                    ExtensionRegistry extensionRegistry) {
         * if (recursionDepth >= recursionLimit) {
         *  throw InvalidProtocolBufferException.RecursionLimitExceeded();
         * }
         ++recursionDepth;
         * builder.WeakMergeFrom(this, extensionRegistry);
         * CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
         * --recursionDepth;
         * }
         *
         * /// <summary>
         * /// Reads a group field value from the stream and merges it into the given
         * /// UnknownFieldSet.
         * /// </summary>
         * [Obsolete]
         * public void ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
         * {
         * if (recursionDepth >= recursionLimit) {
         *  throw InvalidProtocolBufferException.RecursionLimitExceeded();
         * }
         ++recursionDepth;
         * builder.WeakMergeFrom(this);
         * CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
         * --recursionDepth;
         * }
         * ZWL */
        /// <summary>
        /// Reads an embedded message field value from the stream.
        /// </summary>
        public void ReadMessage(PacketDistributed builder)
        {
            int length = (int)ReadRawVarint32();

            if (recursionDepth >= recursionLimit)
            {
                throw InvalidProtocolBufferException.RecursionLimitExceeded();
            }
            int oldLimit = PushLimit(length);

            ++recursionDepth;
            builder.MergeFrom(this, builder);
            CheckLastTagWas(0);
            --recursionDepth;
            PopLimit(oldLimit);
        }
Example #9
0
        /// <summary>
        /// Reads an embedded message field value from the stream.
        /// </summary>
        public void ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
        {
            int length = (int)ReadRawVarint32();

            if (recursionDepth >= recursionLimit)
            {
                throw InvalidProtocolBufferException.RecursionLimitExceeded();
            }
            int oldLimit = PushLimit(length);

            ++recursionDepth;
            builder.WeakMergeFrom(this, extensionRegistry);
            CheckLastTagWas(0);
            --recursionDepth;
            PopLimit(oldLimit);
        }
Example #10
0
        /// <summary>
        /// Called when buffer is empty to read more bytes from the
        /// input.  If <paramref name="mustSucceed"/> is true, RefillBuffer() gurantees that
        /// either there will be at least one byte in the buffer when it returns
        /// or it will throw an exception.  If <paramref name="mustSucceed"/> is false,
        /// RefillBuffer() returns false if no more bytes were available.
        /// </summary>
        /// <param name="mustSucceed"></param>
        /// <returns></returns>
        private bool RefillBuffer(bool mustSucceed)
        {
            if (bufferPos < bufferSize)
            {
                throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
            }

            if (totalBytesRetired + bufferSize == currentLimit)
            {
                // Oops, we hit a limit.
                if (mustSucceed)
                {
                    throw InvalidProtocolBufferException.TruncatedMessage();
                }
                else
                {
                    return(false);
                }
            }

            totalBytesRetired += bufferSize;

            bufferPos  = 0;
            bufferSize = (input == null) ? 0 : input.Read(buffer, 0, buffer.Length);
            if (bufferSize == 0)
            {
                if (mustSucceed)
                {
                    throw InvalidProtocolBufferException.TruncatedMessage();
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                RecomputeBufferSizeAfterLimit();
                int totalBytesRead =
                    totalBytesRetired + bufferSize + bufferSizeAfterLimit;
                if (totalBytesRead > sizeLimit || totalBytesRead < 0)
                {
                    throw InvalidProtocolBufferException.SizeLimitExceeded();
                }
                return(true);
            }
        }
        /// <summary>
        /// Read a raw varint from the stream.
        /// </summary>

        public ulong ReadRawVarint64()
        {
            int   shift  = 0;
            ulong result = 0;

            while (shift < 64)
            {
                byte b = ReadRawByte();
                result |= (ulong)(b & 0x7F) << shift;
                if ((b & 0x80) == 0)
                {
                    return(result);
                }
                shift += 7;
            }
            throw InvalidProtocolBufferException.MalformedVarint();
        }
Example #12
0
        public ulong ReadRawVarint64()
        {
            int   i   = 0;
            ulong num = 0uL;

            while (i < 64)
            {
                byte b = this.ReadRawByte();
                num |= (ulong)((ulong)((long)(b & 127)) << i);
                if ((b & 128) == 0)
                {
                    return(num);
                }
                i += 7;
            }
            throw InvalidProtocolBufferException.MalformedVarint();
        }
Example #13
0
        public int PushLimit(int byteLimit)
        {
            if (byteLimit < 0)
            {
                throw InvalidProtocolBufferException.NegativeSize();
            }
            byteLimit += this.totalBytesRetired + this.bufferPos;
            int num = this.currentLimit;

            if (byteLimit > num)
            {
                throw InvalidProtocolBufferException.TruncatedMessage();
            }
            this.currentLimit = byteLimit;
            this.RecomputeBufferSizeAfterLimit();
            return(num);
        }
Example #14
0
        /// <summary>
        /// Reads and discards <paramref name="size"/> bytes.
        /// </summary>
        /// <exception cref="InvalidProtocolBufferException">the end of the stream
        /// or the current limit was reached</exception>
        public void SkipRawBytes(int size)
        {
            if (size < 0)
            {
                throw InvalidProtocolBufferException.NegativeSize();
            }

            if (totalBytesRetired + bufferPos + size > currentLimit)
            {
                // Read to the end of the stream anyway.
                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
                // Then fail.
                throw InvalidProtocolBufferException.TruncatedMessage();
            }

            if (size < bufferSize - bufferPos)
            {
                // We have all the bytes we need already.
                bufferPos += size;
            }
            else
            {
                // Skipping more bytes than are in the buffer.  First skip what we have.
                int pos = bufferSize - bufferPos;
                totalBytesRetired += pos;
                bufferPos          = 0;
                bufferSize         = 0;

                // Then skip directly from the InputStream for the rest.
                if (pos < size)
                {
                    // TODO(jonskeet): Java implementation uses skip(). Not sure whether this is really equivalent...
                    if (input == null)
                    {
                        throw InvalidProtocolBufferException.TruncatedMessage();
                    }
                    input.Seek(size - pos, SeekOrigin.Current);
                    if (input.Position > input.Length)
                    {
                        throw InvalidProtocolBufferException.TruncatedMessage();
                    }
                    totalBytesRetired += size - pos;
                }
            }
        }
        /// <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 int PushLimit(int byteLimit)
        {
            if (byteLimit < 0)
            {
                throw InvalidProtocolBufferException.NegativeSize();
            }
            byteLimit += totalBytesRetired + bufferPos;
            int oldLimit = currentLimit;

            if (byteLimit > oldLimit)
            {
                throw InvalidProtocolBufferException.TruncatedMessage();
            }
            currentLimit = byteLimit;

            RecomputeBufferSizeAfterLimit();

            return(oldLimit);
        }
Example #16
0
 public void ReadGroupArray <T>(uint fieldTag, string fieldName, ICollection <T> list, T messageType,
                                ExtensionRegistry registry) where T : IMessageLite
 {
     tokenizer.Consume(":");
     tokenizer.Consume("[");
     while (!tokenizer.TryConsume("]"))
     {
         IBuilderLite builder = messageType.WeakCreateBuilderForType();
         if (++recursionDepth >= recursionLimit)
         {
             throw InvalidProtocolBufferException.RecursionLimitExceeded();
         }
         tokenizer.Consume("{");
         builder.WeakMergeFrom(this, registry);
         CheckLastTagWas("}");
         --recursionDepth;
         list.Add((T)builder.WeakBuildPartial());
     }
 }
Example #17
0
 private bool RefillBuffer(bool mustSucceed)
 {
     if (this.bufferPos < this.bufferSize)
     {
         throw new InvalidOperationException("RefillBuffer() called when buffer wasn't empty.");
     }
     if (this.totalBytesRetired + this.bufferSize == this.currentLimit)
     {
         if (mustSucceed)
         {
             throw InvalidProtocolBufferException.TruncatedMessage();
         }
         return(false);
     }
     else
     {
         this.totalBytesRetired += this.bufferSize;
         this.bufferPos          = 0;
         this.bufferSize         = ((this.input == null) ? 0 : this.input.Read(this.buffer, 0, this.buffer.Length));
         if (this.bufferSize < 0)
         {
             throw new InvalidOperationException("Stream.Read returned a negative count");
         }
         if (this.bufferSize == 0)
         {
             if (mustSucceed)
             {
                 throw InvalidProtocolBufferException.TruncatedMessage();
             }
             return(false);
         }
         else
         {
             this.RecomputeBufferSizeAfterLimit();
             int num = this.totalBytesRetired + this.bufferSize + this.bufferSizeAfterLimit;
             if (num > this.sizeLimit || num < 0)
             {
                 throw InvalidProtocolBufferException.SizeLimitExceeded();
             }
             return(true);
         }
     }
 }
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);

            try {
                input.ReadRawVarint32();
                Assert.Fail("Should have thrown an exception.");
            } catch (InvalidProtocolBufferException e) {
                Assert.AreEqual(expected.Message, e.Message);
            }

            input = CodedInputStream.CreateInstance(data);
            try {
                input.ReadRawVarint64();
                Assert.Fail("Should have thrown an exception.");
            } catch (InvalidProtocolBufferException e) {
                Assert.AreEqual(expected.Message, e.Message);
            }
        }
 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
 {
     if (wireType == WireFormat.WireType.Varint)
     {
         WriteUInt64(fieldNumber, null /*not used*/, value);
     }
     else if (wireType == WireFormat.WireType.Fixed32)
     {
         WriteFixed32(fieldNumber, null /*not used*/, (uint)value);
     }
     else if (wireType == WireFormat.WireType.Fixed64)
     {
         WriteFixed64(fieldNumber, null /*not used*/, value);
     }
     else
     {
         throw InvalidProtocolBufferException.InvalidWireType();
     }
 }
Example #20
0
        /// <summary>
        /// Reads a group field value from the stream.
        /// </summary>
        public void ReadGroup(int fieldNumber, IBuilderLite builder,
                              ExtensionRegistry extensionRegistry)
        {
            if (recursionDepth >= recursionLimit)
            {
                throw InvalidProtocolBufferException.RecursionLimitExceeded();
            }
            ++recursionDepth;
            tokenizer.TryConsume(":");
            string endToken = "}";

            if (!tokenizer.TryConsume("{"))
            {
                endToken = ">";
                tokenizer.Consume("<");
            }
            builder.WeakMergeFrom(this, extensionRegistry);
            CheckLastTagWas(endToken);
            --recursionDepth;
        }
Example #21
0
        public bool ReadTag(out uint fieldTag, out string fieldName)
        {
            fieldTag = 0;
            if (hasNextTag)
            {
                fieldName  = nextTag;
                lastTag    = fieldName;
                hasNextTag = false;
                return(true);
            }

            if (IsAtEnd)
            {
                fieldName = null;
                lastTag   = fieldName;
                return(false);
            }

            if (tokenizer.TryConsume("}"))
            {
                fieldName = null;
                lastTag   = "}";
                return(false);
            }

            if (tokenizer.TryConsume(">"))
            {
                fieldName = null;
                lastTag   = ">";
                return(false);
            }

            fieldName = tokenizer.ConsumeIdentifier();
            lastTag   = fieldName;
            if (lastTag == null)
            {
                // If we actually read zero, that's not a valid tag.
                throw InvalidProtocolBufferException.InvalidTag();
            }
            return(true);
        }
        /// <summary>
        /// Reads and discards a single field, given its tag value.
        /// </summary>
        /// <returns>false if the tag is an end-group tag, in which case
        /// nothing is skipped. Otherwise, returns true.</returns>

        /*ZWL
        *
        *  public bool SkipField(uint tag) {
        *  switch (WireFormat.GetTagWireType(tag)) {
        *    case WireFormat.WireType.Varint:
        *      ReadInt32();
        *      return true;
        *    case WireFormat.WireType.Fixed64:
        *      ReadRawLittleEndian64();
        *      return true;
        *    case WireFormat.WireType.LengthDelimited:
        *      SkipRawBytes((int) ReadRawVarint32());
        *      return true;
        *    case WireFormat.WireType.StartGroup:
        *      SkipMessage();
        *      CheckLastTagWas(
        *        WireFormat.MakeTag(WireFormat.GetTagFieldNumber(tag),
        *                           WireFormat.WireType.EndGroup));
        *      return true;
        *    case WireFormat.WireType.EndGroup:
        *      return false;
        *    case WireFormat.WireType.Fixed32:
        *      ReadRawLittleEndian32();
        *      return true;
        *    default:
        *      throw InvalidProtocolBufferException.InvalidWireType();
        *  }
        *  }
        *  ZWL*/
        /// <summary>
        /// Reads and discards an entire message.  This will read either until EOF
        /// or until an endgroup tag, whichever comes first.
        /// </summary>

        /*ZWL
        *  public void SkipMessage() {
        *  while (true) {
        *   uint tag = ReadTag();
        *   if (tag == 0 || !SkipField(tag)) {
        *     return;
        *   }
        *  }
        *  }
        *  ZWL*/
        /// <summary>
        /// Reads and discards <paramref name="size"/> bytes.
        /// </summary>
        /// <exception cref="InvalidProtocolBufferException">the end of the stream
        /// or the current limit was reached</exception>
        public void SkipRawBytes(int size)
        {
            if (size < 0)
            {
                throw InvalidProtocolBufferException.NegativeSize();
            }

            if (totalBytesRetired + bufferPos + size > currentLimit)
            {
                // Read to the end of the stream anyway.
                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
                // Then fail.
                throw InvalidProtocolBufferException.TruncatedMessage();
            }

            if (size <= bufferSize - bufferPos)
            {
                // We have all the bytes we need already.
                bufferPos += size;
            }
            else
            {
                // Skipping more bytes than are in the buffer.  First skip what we have.
                int pos = bufferSize - bufferPos;
                totalBytesRetired += pos;
                bufferPos          = 0;
                bufferSize         = 0;

                // Then skip directly from the InputStream for the rest.
                if (pos < size)
                {
                    if (input == null)
                    {
                        throw InvalidProtocolBufferException.TruncatedMessage();
                    }
                    SkipImpl(size - pos);
                    totalBytesRetired += size - pos;
                }
            }
        }
Example #23
0
            public bool MergeFieldFrom(uint tag, CodedInputStream input)
            {
                int number = WireFormat.GetTagFieldNumber(tag);

                switch (WireFormat.GetTagWireType(tag))
                {
                case WireFormat.WireType.Varint:
                    GetFieldBuilder(number).AddVarint(input.ReadUInt64());
                    return(true);

                case WireFormat.WireType.Fixed64:
                    GetFieldBuilder(number).AddFixed64(input.ReadFixed64());
                    return(true);

                case WireFormat.WireType.LengthDelimited:
                    GetFieldBuilder(number).AddLengthDelimited(input.ReadBytes());
                    return(true);

                case WireFormat.WireType.StartGroup: {
                    Builder subBuilder = CreateBuilder();
#pragma warning disable 0612
                    input.ReadUnknownGroup(number, subBuilder);
#pragma warning restore 0612
                    GetFieldBuilder(number).AddGroup(subBuilder.Build());
                    return(true);
                }

                case WireFormat.WireType.EndGroup:
                    return(false);

                case WireFormat.WireType.Fixed32:
                    GetFieldBuilder(number).AddFixed32(input.ReadFixed32());
                    return(true);

                default:
                    throw InvalidProtocolBufferException.InvalidWireType();
                }
            }
        public IEnumerator <TMessage> GetEnumerator()
        {
            using (Stream stream = streamProvider())
            {
                CodedInputStream input = CodedInputStream.CreateInstance(stream);
                input.SetSizeLimit(sizeLimit);
                uint   tag;
                string name;
                while (input.ReadTag(out tag, out name))
                {
                    if ((tag == 0 && name == "item") || (tag == ExpectedTag))
                    {
                        yield return(messageReader(input, extensionRegistry));
                    }
                    else
                    {
                        throw InvalidProtocolBufferException.InvalidMessageStreamTag();
                    }

                    input.ResetSizeCounter();
                }
            }
        }
Example #25
0
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);

            try
            {
                input.ReadRawVarint32();
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }

            input = CodedInputStream.CreateInstance(data);
            try
            {
                input.ReadRawVarint64();
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }

            // Make sure we get the same error when reading directly from a Stream.
            try
            {
                CodedInputStream.ReadRawVarint32(new MemoryStream(data));
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }
        }
Example #26
0
 public bool ReadTag(out uint fieldTag, out string fieldName)
 {
     fieldName = null;
     if (this.hasNextTag)
     {
         fieldTag        = this.nextTag;
         this.lastTag    = fieldTag;
         this.hasNextTag = false;
         return(true);
     }
     if (this.IsAtEnd)
     {
         fieldTag     = 0u;
         this.lastTag = fieldTag;
         return(false);
     }
     fieldTag     = this.ReadRawVarint32();
     this.lastTag = fieldTag;
     if (this.lastTag == 0u)
     {
         throw InvalidProtocolBufferException.InvalidTag();
     }
     return(true);
 }
Example #27
0
        public void ReadVarint()
        {
            AssertReadVarint(Bytes(0x00), 0);
            AssertReadVarint(Bytes(0x01), 1);
            AssertReadVarint(Bytes(0x7f), 127);
            // 14882
            AssertReadVarint(Bytes(0xa2, 0x74), (0x22 << 0) | (0x74 << 7));
            // 2961488830
            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b),
                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
                             (0x0bL << 28));

            // 64-bit
            // 7256456126
            AssertReadVarint(Bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b),
                             (0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) |
                             (0x1bL << 28));
            // 41256202580718336
            AssertReadVarint(Bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49),
                             (0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) |
                             (0x43L << 28) | (0x49L << 35) | (0x24L << 42) | (0x49L << 49));
            // 11964378330978735131
            AssertReadVarint(Bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01),
                             (0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
                             (0x3bUL << 28) | (0x56UL << 35) | (0x00UL << 42) |
                             (0x05UL << 49) | (0x26UL << 56) | (0x01UL << 63));

            // Failures
            AssertReadVarintFailure(
                InvalidProtocolBufferException.MalformedVarint(),
                Bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
                      0x00));
            AssertReadVarintFailure(
                InvalidProtocolBufferException.TruncatedMessage(),
                Bytes(0x80));
        }
Example #28
0
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            var exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint32());
            Assert.AreEqual(expected.Message, exception.Message);

            input = CodedInputStream.CreateInstance(data);
            exception = Assert.Throws<InvalidProtocolBufferException>(() => input.ReadRawVarint64());
            Assert.AreEqual(expected.Message, exception.Message);

            // Make sure we get the same error when reading directly from a Stream.
            exception = Assert.Throws<InvalidProtocolBufferException>(() => CodedInputStream.ReadRawVarint32(new MemoryStream(data)));
            Assert.AreEqual(expected.Message, exception.Message);
        }
Example #29
0
            /// <summary>
            /// Called by MergeFieldFrom to parse a MessageSet extension.
            /// </summary>
            private void MergeMessageSetExtensionFromCodedStream(ICodedInputStream input,
                                                                 ExtensionRegistry extensionRegistry, IBuilder builder)
            {
                MessageDescriptor type = builder.DescriptorForType;

                // The wire format for MessageSet is:
                //   message MessageSet {
                //     repeated group Item = 1 {
                //       required int32 typeId = 2;
                //       required bytes message = 3;
                //     }
                //   }
                // "typeId" is the extension's field number.  The extension can only be
                // a message type, where "message" contains the encoded bytes of that
                // message.
                //
                // In practice, we will probably never see a MessageSet item in which
                // the message appears before the type ID, or where either field does not
                // appear exactly once.  However, in theory such cases are valid, so we
                // should be prepared to accept them.

                int             typeId     = 0;
                ByteString      rawBytes   = null; // If we encounter "message" before "typeId"
                IBuilderLite    subBuilder = null;
                FieldDescriptor field      = null;

                uint   lastTag = WireFormat.MessageSetTag.ItemStart;
                uint   tag;
                string name;

                while (input.ReadTag(out tag, out name))
                {
                    if (tag == 0 && name != null)
                    {
                        if (name == "type_id")
                        {
                            tag = WireFormat.MessageSetTag.TypeID;
                        }
                        else if (name == "message")
                        {
                            tag = WireFormat.MessageSetTag.Message;
                        }
                    }
                    if (tag == 0)
                    {
                        if (input.SkipField())
                        {
                            continue; //can't merge unknown without field tag
                        }
                        break;
                    }

                    lastTag = tag;
                    if (tag == WireFormat.MessageSetTag.TypeID)
                    {
                        typeId = 0;
                        // Zero is not a valid type ID.
                        if (input.ReadInt32(ref typeId) && typeId != 0)
                        {
                            ExtensionInfo extension = extensionRegistry[type, typeId];
                            if (extension != null)
                            {
                                field      = extension.Descriptor;
                                subBuilder = extension.DefaultInstance.WeakCreateBuilderForType();
                                IMessageLite originalMessage = (IMessageLite)builder[field];
                                if (originalMessage != null)
                                {
                                    subBuilder.WeakMergeFrom(originalMessage);
                                }
                                if (rawBytes != null)
                                {
                                    // We already encountered the message.  Parse it now.
                                    // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes.
                                    // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry?
                                    subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput());
                                    rawBytes = null;
                                }
                            }
                            else
                            {
                                // Unknown extension number.  If we already saw data, put it
                                // in rawBytes.
                                if (rawBytes != null)
                                {
                                    MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
                                    rawBytes = null;
                                }
                            }
                        }
                    }
                    else if (tag == WireFormat.MessageSetTag.Message)
                    {
                        if (subBuilder != null)
                        {
                            // We already know the type, so we can parse directly from the input
                            // with no copying.  Hooray!
                            input.ReadMessage(subBuilder, extensionRegistry);
                        }
                        else if (input.ReadBytes(ref rawBytes))
                        {
                            if (typeId != 0)
                            {
                                // We don't know how to parse this.  Ignore it.
                                MergeField(typeId,
                                           UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build());
                            }
                        }
                    }
                    else
                    {
                        // Unknown tag.  Skip it.
                        if (!input.SkipField())
                        {
                            break; // end of group
                        }
                    }
                }

                if (lastTag != WireFormat.MessageSetTag.ItemEnd)
                {
                    throw InvalidProtocolBufferException.InvalidEndTag();
                }

                if (subBuilder != null)
                {
                    builder[field] = subBuilder.WeakBuild();
                }
            }
Example #30
0
            /// <summary>
            /// Parse a single field from <paramref name="input"/> and merge it
            /// into this set.
            /// </summary>
            /// <param name="tag">The field's tag number, which was already parsed.</param>
            /// <param name="input">The coded input stream containing the field</param>
            /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
            public bool MergeFieldFrom(uint tag, ICodedInputStream input)
            {
                if (tag == 0)
                {
                    input.SkipField();
                    return(true);
                }

                int number = WireFormat.GetTagFieldNumber(tag);

                switch (WireFormat.GetTagWireType(tag))
                {
                case WireFormat.WireType.Varint:
                {
                    ulong uint64 = 0;
                    if (input.ReadUInt64(ref uint64))
                    {
                        GetFieldBuilder(number).AddVarint(uint64);
                    }
                    return(true);
                }

                case WireFormat.WireType.Fixed32:
                {
                    uint uint32 = 0;
                    if (input.ReadFixed32(ref uint32))
                    {
                        GetFieldBuilder(number).AddFixed32(uint32);
                    }
                    return(true);
                }

                case WireFormat.WireType.Fixed64:
                {
                    ulong uint64 = 0;
                    if (input.ReadFixed64(ref uint64))
                    {
                        GetFieldBuilder(number).AddFixed64(uint64);
                    }
                    return(true);
                }

                case WireFormat.WireType.LengthDelimited:
                {
                    ByteString bytes = null;
                    if (input.ReadBytes(ref bytes))
                    {
                        GetFieldBuilder(number).AddLengthDelimited(bytes);
                    }
                    return(true);
                }

                case WireFormat.WireType.StartGroup:
                {
                    Builder subBuilder = CreateBuilder();
#pragma warning disable 0612
                    input.ReadUnknownGroup(number, subBuilder);
#pragma warning restore 0612
                    GetFieldBuilder(number).AddGroup(subBuilder.Build());
                    return(true);
                }

                case WireFormat.WireType.EndGroup:
                    return(false);

                default:
                    throw InvalidProtocolBufferException.InvalidWireType();
                }
            }
        /// <summary>
        /// Read 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 byte[] ReadRawBytes(int size)
        {
            if (size < 0)
            {
                throw InvalidProtocolBufferException.NegativeSize();
            }

            if (totalBytesRetired + bufferPos + size > currentLimit)
            {
                // Read to the end of the stream anyway.
                SkipRawBytes(currentLimit - totalBytesRetired - bufferPos);
                // Then fail.
                throw InvalidProtocolBufferException.TruncatedMessage();
            }

            if (size <= bufferSize - bufferPos)
            {
                // We have all the bytes we need already.
                byte[] bytes = new byte[size];
                Array.Copy(buffer, bufferPos, bytes, 0, size);
                bufferPos += size;
                return(bytes);
            }
            else if (size < BufferSize)
            {
                // Reading more bytes than are in the buffer, but not an excessive number
                // of bytes.  We can safely allocate the resulting array ahead of time.

                // First copy what we have.
                byte[] bytes = new byte[size];
                int    pos   = bufferSize - bufferPos;
                Array.Copy(buffer, bufferPos, bytes, 0, pos);
                bufferPos = bufferSize;

                // We want to use RefillBuffer() and then copy from the buffer into our
                // byte array rather than reading directly into our byte array because
                // the input may be unbuffered.
                RefillBuffer(true);

                while (size - pos > bufferSize)
                {
                    Array.Copy(buffer, 0, bytes, pos, bufferSize);
                    pos      += bufferSize;
                    bufferPos = bufferSize;
                    RefillBuffer(true);
                }

                Array.Copy(buffer, 0, bytes, pos, size - pos);
                bufferPos = size - pos;

                return(bytes);
            }
            else
            {
                // The size is very large.  For security reasons, we can't allocate the
                // entire byte array yet.  The size comes directly from the input, so a
                // maliciously-crafted message could provide a bogus very large size in
                // order to trick the app into allocating a lot of memory.  We avoid this
                // by allocating and reading only a small chunk at a time, so that the
                // malicious message must actually *be* extremely large to cause
                // problems.  Meanwhile, we limit the allowed size of a message elsewhere.

                // Remember the buffer markers since we'll have to copy the bytes out of
                // it later.
                int originalBufferPos  = bufferPos;
                int originalBufferSize = bufferSize;

                // Mark the current buffer consumed.
                totalBytesRetired += bufferSize;
                bufferPos          = 0;
                bufferSize         = 0;

                // Read all the rest of the bytes we need.
                int           sizeLeft = size - (originalBufferSize - originalBufferPos);
                List <byte[]> chunks   = new List <byte[]>();

                while (sizeLeft > 0)
                {
                    byte[] chunk = new byte[Math.Min(sizeLeft, BufferSize)];
                    int    pos   = 0;
                    while (pos < chunk.Length)
                    {
                        int n = (input == null) ? -1 : input.Read(chunk, pos, chunk.Length - pos);
                        if (n <= 0)
                        {
                            throw InvalidProtocolBufferException.TruncatedMessage();
                        }
                        totalBytesRetired += n;
                        pos += n;
                    }
                    sizeLeft -= chunk.Length;
                    chunks.Add(chunk);
                }

                // OK, got everything.  Now concatenate it all into one buffer.
                byte[] bytes = new byte[size];

                // Start by copying the leftover bytes from this.buffer.
                int newPos = originalBufferSize - originalBufferPos;
                Array.Copy(buffer, originalBufferPos, bytes, 0, newPos);

                // And now all the chunks.
                foreach (byte[] chunk in chunks)
                {
                    Array.Copy(chunk, 0, bytes, newPos, chunk.Length);
                    newPos += chunk.Length;
                }

                // Done.
                return(bytes);
            }
        }
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private static void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
            try
            {
                input.ReadRawVarint32();
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }

            input = CodedInputStream.CreateInstance(data);
            try
            {
                input.ReadRawVarint64();
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }

            // Make sure we get the same error when reading directly from a Stream.
            try
            {
                CodedInputStream.ReadRawVarint32(new MemoryStream(data));
                Assert.Fail("Should have thrown an exception.");
            }
            catch (InvalidProtocolBufferException e)
            {
                Assert.AreEqual(expected.Message, e.Message);
            }
        }
        /// <summary>
        /// Parses the given bytes using ReadRawVarint32() and ReadRawVarint64() and
        /// expects them to fail with an InvalidProtocolBufferException whose
        /// description matches the given one.
        /// </summary>
        private void AssertReadVarintFailure(InvalidProtocolBufferException expected, byte[] data)
        {
            CodedInputStream input = CodedInputStream.CreateInstance(data);
              try {
            input.ReadRawVarint32();
            Assert.Fail("Should have thrown an exception.");
              } catch (InvalidProtocolBufferException e) {
            Assert.AreEqual(expected.Message, e.Message);
              }

              input = CodedInputStream.CreateInstance(data);
              try {
            input.ReadRawVarint64();
            Assert.Fail("Should have thrown an exception.");
              } catch (InvalidProtocolBufferException e) {
            Assert.AreEqual(expected.Message, e.Message);
              }
        }