diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs index 1216b2005cdf..0428fb54e672 100644 --- a/csharp/src/Google.Protobuf/CodedInputStream.cs +++ b/csharp/src/Google.Protobuf/CodedInputStream.cs @@ -108,7 +108,6 @@ public sealed class CodedInputStream : IDisposable /// The absolute position of the end of the current message. /// private int currentLimit = int.MaxValue; - private uint tagLimit = uint.MaxValue; private int recursionDepth = 0; @@ -384,7 +383,7 @@ public uint ReadTag() // If we actually read a tag with a field of 0, that's not a valid tag. throw InvalidProtocolBufferException.InvalidTag(); } - if (ReachedLimit || ReachedTagLimit) + if (ReachedLimit) { return 0; } @@ -605,15 +604,9 @@ public void ReadGroup(IMessage builder) { throw InvalidProtocolBufferException.RecursionLimitExceeded(); } - uint oldTag = PushTag(); ++recursionDepth; builder.MergeFrom(this); - if (!ReachedTagLimit) - { - throw InvalidProtocolBufferException.TruncatedMessage(); - } --recursionDepth; - PopTag(oldTag); } /// @@ -978,19 +971,6 @@ internal int PushLimit(int byteLimit) return oldLimit; } - /// - /// Sets tagLimit to the limit calculated by the last tag. - /// This is called when descending into a group message. The previous limit is returns. - /// - /// The old limit - internal uint PushTag() - { - uint oldLimit = tagLimit; - uint newLimit = WireFormat.MakeTag(WireFormat.GetTagFieldNumber(LastTag), WireFormat.WireType.EndGroup); - tagLimit = newLimit; - return oldLimit; - } - private void RecomputeBufferSizeAfterLimit() { bufferSize += bufferSizeAfterLimit; @@ -1016,14 +996,6 @@ internal void PopLimit(int oldLimit) RecomputeBufferSizeAfterLimit(); } - /// - /// Discards the current limit, returning the previous limit - /// - internal void PopTag(uint oldTag) - { - tagLimit = oldTag; - } - /// /// Returns whether or not all the data before the limit has been read. /// @@ -1041,14 +1013,6 @@ internal bool ReachedLimit } } - internal bool ReachedTagLimit - { - get - { - return tagLimit == lastTag; - } - } - /// /// Returns true if the stream has reached the end of the input. This is the /// case if either the end of the underlying input source has been reached or diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs index 6a92fb9d97d9..9121567621a1 100644 --- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs +++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs @@ -183,7 +183,7 @@ internal UnknownFieldSet AddOrReplaceField(int number, UnknownField field) /// /// The coded input stream containing the field /// false if the tag is an "end group" tag, true otherwise - private void MergeFieldFrom(CodedInputStream input) + private bool MergeFieldFrom(CodedInputStream input) { uint tag = input.LastTag; int number = WireFormat.GetTagFieldNumber(tag); @@ -193,25 +193,25 @@ private void MergeFieldFrom(CodedInputStream input) { ulong uint64 = input.ReadUInt64(); GetOrAddField(number).AddVarint(uint64); - return; + return true; } case WireFormat.WireType.Fixed32: { uint uint32 = input.ReadFixed32(); GetOrAddField(number).AddFixed32(uint32); - return; + return true; } case WireFormat.WireType.Fixed64: { ulong uint64 = input.ReadFixed64(); GetOrAddField(number).AddFixed64(uint64); - return; + return true; } case WireFormat.WireType.LengthDelimited: { ByteString bytes = input.ReadBytes(); GetOrAddField(number).AddLengthDelimited(bytes); - return; + return true; } case WireFormat.WireType.StartGroup: { @@ -222,11 +222,11 @@ private void MergeFieldFrom(CodedInputStream input) set.MergeFieldFrom(input); } GetOrAddField(number).AddGroup(set); - return; + return true; } case WireFormat.WireType.EndGroup: { - throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); + return false; } default: throw new InvalidOperationException("Wire Type is invalid."); @@ -254,8 +254,34 @@ public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields, { unknownFields = new UnknownFieldSet(); } - unknownFields.MergeFieldFrom(input); + if (!unknownFields.MergeFieldFrom(input)) + { + throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen + } return unknownFields; + } + + /// + /// Create a new UnknownFieldSet if unknownFields is null. + /// Parse a single field from and merge it + /// into unknownFields. If is configured to discard unknown fields, + /// will be returned as-is and the field will be skipped. + /// + /// The UnknownFieldSet which need to be merged + /// The coded input stream containing the field + /// The merged UnknownFieldSet + public static bool MergeFieldFrom(ref UnknownFieldSet unknownFields, CodedInputStream input) + { + if (input.DiscardUnknownFields) + { + input.SkipLastField(); + return true; + } + if (unknownFields == null) + { + unknownFields = new UnknownFieldSet(); + } + return unknownFields.MergeFieldFrom(input); } ///