/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); }
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(); }
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); }
/// <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); }
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()); } }
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(); } }
/// <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; }
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; } } }
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(); } } }
/// <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); } }
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); }
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)); }
/// <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); }
/// <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(); } }
/// <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); } }