public void ReadInvalidUtf8() { MemoryStream ms = new MemoryStream(); CodedOutputStream output = CodedOutputStream.CreateInstance(ms); uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); output.WriteRawVarint32(tag); output.WriteRawVarint32(1); output.WriteRawBytes(new byte[] { 0x80 }); output.Flush(); ms.Position = 0; CodedInputStream input = CodedInputStream.CreateInstance(ms); uint testtag; string ignored; Assert.IsTrue(input.ReadTag(out testtag, out ignored)); Assert.AreEqual(tag, testtag); string text = null; input.ReadString(ref text); Assert.AreEqual('\ufffd', text[0]); }
public bool SkipField() { uint tag = this.lastTag; switch (WireFormat.GetTagWireType(tag)) { case WireFormat.WireType.Varint: this.ReadRawVarint64(); return(true); case WireFormat.WireType.Fixed64: this.ReadRawLittleEndian64(); return(true); case WireFormat.WireType.LengthDelimited: this.SkipRawBytes((int)this.ReadRawVarint32()); return(true); case WireFormat.WireType.StartGroup: this.SkipMessage(); this.CheckLastTagWas(WireFormat.MakeTag(WireFormat.GetTagFieldNumber(tag), WireFormat.WireType.EndGroup)); return(true); case WireFormat.WireType.EndGroup: return(false); case WireFormat.WireType.Fixed32: this.ReadRawLittleEndian32(); return(true); default: throw InvalidProtocolBufferException.InvalidWireType(); } }
public void ReadMaliciouslyLargeBlob() { MemoryStream ms = new MemoryStream(); CodedOutputStream output = CodedOutputStream.CreateInstance(ms); uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); output.WriteRawVarint32(tag); output.WriteRawVarint32(0x7FFFFFFF); output.WriteRawBytes(new byte[32]); // Pad with a few random bytes. output.Flush(); ms.Position = 0; CodedInputStream input = CodedInputStream.CreateInstance(ms); uint testtag; string ignore; Assert.IsTrue(input.ReadTag(out testtag, out ignore)); Assert.AreEqual(tag, testtag); try { ByteString bytes = null; input.ReadBytes(ref bytes); Assert.Fail("Should have thrown an exception!"); } catch (InvalidProtocolBufferException) { // success. } }
public void ReadMaliciouslyLargeBlob() { MemoryStream ms = new MemoryStream(); CodedOutputStream output = CodedOutputStream.CreateInstance(ms); uint tag = WireFormat.MakeTag(1, WireFormat.WireType.LengthDelimited); output.WriteRawVarint32(tag); output.WriteRawVarint32(0x7FFFFFFF); output.WriteRawBytes(new byte[32]); // Pad with a few random bytes. output.Flush(); ms.Position = 0; CodedInputStream input = CodedInputStream.CreateInstance(ms); uint testtag; string ignore; Assert.IsTrue(input.ReadTag(out testtag, out ignore)); Assert.AreEqual(tag, testtag); ByteString bytes = null; // TODO(jonskeet): Should this be ArgumentNullException instead? Assert.Throws <InvalidProtocolBufferException>(() => input.ReadBytes(ref bytes)); }
public void ReadUnknownGroup(int fieldNumber, IBuilderLite builder) { if (this.recursionDepth >= this.recursionLimit) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } this.recursionDepth++; builder.WeakMergeFrom(this); this.CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); this.recursionDepth--; }
/// <summary> /// Reads a group field value from the stream and merges it into the given /// UnknownFieldSet. /// </summary> public void ReadUnknownGroup(int fieldNumber, UnknownFieldSet.Builder builder) { if (recursionDepth >= recursionLimit) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } ++recursionDepth; builder.MergeFrom(this); CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); --recursionDepth; }
/// <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; builder.WeakMergeFrom(this, extensionRegistry); CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup)); --recursionDepth; }
internal void MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) { uint tag; string name; while (input.ReadTag(out tag, out name)) { if (tag == 0 && name != null) { FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(name); if (fieldByName != null) { tag = WireFormat.MakeTag(fieldByName); } else { ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, name); if (extension != null) { tag = WireFormat.MakeTag(extension.Descriptor); } } } if (tag == 0) { if (input.SkipField()) { continue; //can't merge unknown without field tag } break; } if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name)) { // end group tag break; } } }
/// <summary> /// Like <see cref="MergeFrom(ICodedInputStream, ExtensionRegistry, IBuilder)" /> /// but parses a single field. /// </summary> /// <param name="input">The input to read the field from</param> /// <param name="extensionRegistry">Registry to use when an extension field is encountered</param> /// <param name="builder">Builder to merge field into, if it's a known field</param> /// <param name="tag">The tag, which should already have been read from the input</param> /// <returns>true unless the tag is an end-group tag</returns> internal bool MergeFieldFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder, uint tag, string fieldName) { if (tag == 0 && fieldName != null) { FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(fieldName); if (fieldByName != null) { tag = WireFormat.MakeTag(fieldByName); } else { ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, fieldName); if (extension != null) { tag = WireFormat.MakeTag(extension.Descriptor); } } } MessageDescriptor type = builder.DescriptorForType; if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) { MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder); return(true); } WireFormat.WireType wireType = WireFormat.GetTagWireType(tag); int fieldNumber = WireFormat.GetTagFieldNumber(tag); FieldDescriptor field; IMessageLite defaultFieldInstance = null; if (type.IsExtensionNumber(fieldNumber)) { ExtensionInfo extension = extensionRegistry[type, fieldNumber]; if (extension == null) { field = null; } else { field = extension.Descriptor; defaultFieldInstance = extension.DefaultInstance; } } else { field = type.FindFieldByNumber(fieldNumber); } // Unknown field or wrong wire type. Skip. if (field == null) { return(MergeFieldFrom(tag, input)); } if (wireType != WireFormat.GetWireType(field)) { WireFormat.WireType expectedType = WireFormat.GetWireType(field.FieldType); if (wireType == expectedType) { //Allowed as of 2.3, this is unpacked data for a packed array } else if (field.IsRepeated && wireType == WireFormat.WireType.LengthDelimited && (expectedType == WireFormat.WireType.Varint || expectedType == WireFormat.WireType.Fixed32 || expectedType == WireFormat.WireType.Fixed64)) { //Allowed as of 2.3, this is packed data for an unpacked array } else { return(MergeFieldFrom(tag, input)); } } switch (field.FieldType) { case FieldType.Group: case FieldType.Message: { IBuilderLite subBuilder = (defaultFieldInstance != null) ? defaultFieldInstance.WeakCreateBuilderForType() : builder.CreateBuilderForField(field); if (!field.IsRepeated) { subBuilder.WeakMergeFrom((IMessageLite)builder[field]); if (field.FieldType == FieldType.Group) { input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry); } else { input.ReadMessage(subBuilder, extensionRegistry); } builder[field] = subBuilder.WeakBuild(); } else { List <IMessageLite> list = new List <IMessageLite>(); if (field.FieldType == FieldType.Group) { input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry); } else { input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, extensionRegistry); } foreach (IMessageLite m in list) { builder.WeakAddRepeatedField(field, m); } return(true); } break; } case FieldType.Enum: { if (!field.IsRepeated) { object unknown; IEnumLite value = null; if (input.ReadEnum(ref value, out unknown, field.EnumType)) { builder[field] = value; } else if (unknown is int) { MergeVarintField(fieldNumber, (ulong)(int)unknown); } } else { ICollection <object> unknown; List <IEnumLite> list = new List <IEnumLite>(); input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType); foreach (IEnumLite en in list) { builder.WeakAddRepeatedField(field, en); } if (unknown != null) { foreach (object oval in unknown) { if (oval is int) { MergeVarintField(fieldNumber, (ulong)(int)oval); } } } } break; } default: { if (!field.IsRepeated) { object value = null; if (input.ReadPrimitiveField(field.FieldType, ref value)) { builder[field] = value; } } else { List <object> list = new List <object>(); input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list); foreach (object oval in list) { builder.WeakAddRepeatedField(field, oval); } } break; } } return(true); }
/// <summary> /// Compute the number of bytes that would be needed to encode a tag. /// </summary> public static int ComputeTagSize(int fieldNumber) { return(ComputeRawVarint32Size(WireFormat.MakeTag(fieldNumber, 0))); }
/// <summary> /// Encodes and writes a tag. /// </summary> public void WriteTag(int fieldNumber, WireFormat.WireType type) { WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type)); }