瀏覽代碼

Added recursion limits to AbstractReader.cs

csharptest 14 年之前
父節點
當前提交
3b70dd78ec

+ 55 - 51
protos/extest/unittest_extras_xmltest.proto

@@ -1,53 +1,57 @@
-// Additional options required for C# generation. File from copyright
-// line onwards is as per original distribution.
-import "google/protobuf/csharp_options.proto";
-option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.TestProtos";
-option (google.protobuf.csharp_file_options).umbrella_classname = "UnitTestXmlSerializerTestProtoFile";
-
-package protobuf_unittest_extra;
-
-option optimize_for = SPEED;
-
-enum EnumOptions {
-    ONE = 0;
-    TWO = 1;
-    THREE = 2;
-}
-
-message TestXmlChild
-{
-    repeated EnumOptions options = 3;
-    optional bytes binary = 4;
-}
-
-message TestXmlNoFields {
-}
-
-message TestXmlMessage {
-
-    optional int64 number = 6;
-    repeated int32 numbers = 2;
-    optional string text = 3;
-    repeated string textlines = 700;
-    optional bool valid = 5;
-    
-    optional TestXmlChild child = 1;
-    repeated group Children = 401 
-    {
-        repeated EnumOptions options = 3;
+// Additional options required for C# generation. File from copyright
+// line onwards is as per original distribution.
+import "google/protobuf/csharp_options.proto";
+option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.TestProtos";
+option (google.protobuf.csharp_file_options).umbrella_classname = "UnitTestXmlSerializerTestProtoFile";
+
+package protobuf_unittest_extra;
+
+option optimize_for = SPEED;
+
+enum EnumOptions {
+    ONE = 0;
+    TWO = 1;
+    THREE = 2;
+}
+
+message TestXmlChild
+{
+    repeated EnumOptions options = 3;
+    optional bytes binary = 4;
+}
+
+message TestXmlNoFields {
+}
+
+message TestXmlRescursive {
+    optional TestXmlRescursive child = 1;
+}
+
+message TestXmlMessage {
+
+    optional int64 number = 6;
+    repeated int32 numbers = 2;
+    optional string text = 3;
+    repeated string textlines = 700;
+    optional bool valid = 5;
+    
+    optional TestXmlChild child = 1;
+    repeated group Children = 401 
+    {
+        repeated EnumOptions options = 3;
         optional bytes binary = 4;
     }
-
-    extensions 100 to 199;
-}
-
-message  TestXmlExtension {
-  required int32 number = 1;
-}
-  
-extend TestXmlMessage {
-  optional EnumOptions extension_enum = 101;
-  optional string extension_text = 102;
-  repeated int32 extension_number = 103 [packed = true];
-  optional TestXmlExtension extension_message = 199;
-}
+
+    extensions 100 to 199;
+}
+
+message  TestXmlExtension {
+  required int32 number = 1;
+}
+  
+extend TestXmlMessage {
+  optional EnumOptions extension_enum = 101;
+  optional string extension_text = 102;
+  repeated int32 extension_number = 103 [packed = true];
+  optional TestXmlExtension extension_message = 199;
+}

+ 291 - 21
src/ProtocolBuffers.Test/TestProtos/UnitTestXmlSerializerTestProtoFile.cs

@@ -35,6 +35,8 @@ namespace Google.ProtocolBuffers.TestProtos {
     internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlChild, global::Google.ProtocolBuffers.TestProtos.TestXmlChild.Builder> internal__static_protobuf_unittest_extra_TestXmlChild__FieldAccessorTable;
     internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor;
     internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields, global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.Builder> internal__static_protobuf_unittest_extra_TestXmlNoFields__FieldAccessorTable;
+    internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlRescursive__Descriptor;
+    internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive, global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Builder> internal__static_protobuf_unittest_extra_TestXmlRescursive__FieldAccessorTable;
     internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor;
     internal static pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Builder> internal__static_protobuf_unittest_extra_TestXmlMessage__FieldAccessorTable;
     internal static pbd::MessageDescriptor internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor;
@@ -54,25 +56,27 @@ namespace Google.ProtocolBuffers.TestProtos {
           "YnVmX3VuaXR0ZXN0X2V4dHJhGiRnb29nbGUvcHJvdG9idWYvY3NoYXJwX29w" + 
           "dGlvbnMucHJvdG8iVQoMVGVzdFhtbENoaWxkEjUKB29wdGlvbnMYAyADKA4y" + 
           "JC5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5FbnVtT3B0aW9ucxIOCgZiaW5h" + 
-          "cnkYBCABKAwiEQoPVGVzdFhtbE5vRmllbGRzIrcCCg5UZXN0WG1sTWVzc2Fn" + 
-          "ZRIOCgZudW1iZXIYBiABKAMSDwoHbnVtYmVycxgCIAMoBRIMCgR0ZXh0GAMg" + 
-          "ASgJEhIKCXRleHRsaW5lcxi8BSADKAkSDQoFdmFsaWQYBSABKAgSNAoFY2hp" + 
-          "bGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sQ2hp" + 
-          "bGQSQwoIY2hpbGRyZW4YkQMgAygKMjAucHJvdG9idWZfdW5pdHRlc3RfZXh0" + 
-          "cmEuVGVzdFhtbE1lc3NhZ2UuQ2hpbGRyZW4aUQoIQ2hpbGRyZW4SNQoHb3B0" + 
-          "aW9ucxgDIAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2V4dHJhLkVudW1PcHRp" + 
-          "b25zEg4KBmJpbmFyeRgEIAEoDCoFCGQQyAEiIgoQVGVzdFhtbEV4dGVuc2lv" + 
-          "bhIOCgZudW1iZXIYASACKAUqKgoLRW51bU9wdGlvbnMSBwoDT05FEAASBwoD" + 
-          "VFdPEAESCQoFVEhSRUUQAjplCg5leHRlbnNpb25fZW51bRInLnByb3RvYnVm" + 
-          "X3VuaXR0ZXN0X2V4dHJhLlRlc3RYbWxNZXNzYWdlGGUgASgOMiQucHJvdG9i" + 
-          "dWZfdW5pdHRlc3RfZXh0cmEuRW51bU9wdGlvbnM6PwoOZXh0ZW5zaW9uX3Rl" + 
-          "eHQSJy5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sTWVzc2FnZRhm" + 
-          "IAEoCTpFChBleHRlbnNpb25fbnVtYmVyEicucHJvdG9idWZfdW5pdHRlc3Rf" + 
-          "ZXh0cmEuVGVzdFhtbE1lc3NhZ2UYZyADKAVCAhABOm4KEWV4dGVuc2lvbl9t" + 
-          "ZXNzYWdlEicucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEuVGVzdFhtbE1lc3Nh" + 
-          "Z2UYxwEgASgLMikucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEuVGVzdFhtbEV4" + 
-          "dGVuc2lvbkJMSAHCPkcKIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMuVGVzdFBy" + 
-          "b3RvcxIiVW5pdFRlc3RYbWxTZXJpYWxpemVyVGVzdFByb3RvRmlsZQ==");
+          "cnkYBCABKAwiEQoPVGVzdFhtbE5vRmllbGRzIk4KEVRlc3RYbWxSZXNjdXJz" + 
+          "aXZlEjkKBWNoaWxkGAEgASgLMioucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEu" + 
+          "VGVzdFhtbFJlc2N1cnNpdmUitwIKDlRlc3RYbWxNZXNzYWdlEg4KBm51bWJl" + 
+          "chgGIAEoAxIPCgdudW1iZXJzGAIgAygFEgwKBHRleHQYAyABKAkSEgoJdGV4" + 
+          "dGxpbmVzGLwFIAMoCRINCgV2YWxpZBgFIAEoCBI0CgVjaGlsZBgBIAEoCzIl" + 
+          "LnByb3RvYnVmX3VuaXR0ZXN0X2V4dHJhLlRlc3RYbWxDaGlsZBJDCghjaGls" + 
+          "ZHJlbhiRAyADKAoyMC5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1s" + 
+          "TWVzc2FnZS5DaGlsZHJlbhpRCghDaGlsZHJlbhI1CgdvcHRpb25zGAMgAygO" + 
+          "MiQucHJvdG9idWZfdW5pdHRlc3RfZXh0cmEuRW51bU9wdGlvbnMSDgoGYmlu" + 
+          "YXJ5GAQgASgMKgUIZBDIASIiChBUZXN0WG1sRXh0ZW5zaW9uEg4KBm51bWJl" + 
+          "chgBIAIoBSoqCgtFbnVtT3B0aW9ucxIHCgNPTkUQABIHCgNUV08QARIJCgVU" + 
+          "SFJFRRACOmUKDmV4dGVuc2lvbl9lbnVtEicucHJvdG9idWZfdW5pdHRlc3Rf" + 
+          "ZXh0cmEuVGVzdFhtbE1lc3NhZ2UYZSABKA4yJC5wcm90b2J1Zl91bml0dGVz" + 
+          "dF9leHRyYS5FbnVtT3B0aW9uczo/Cg5leHRlbnNpb25fdGV4dBInLnByb3Rv" + 
+          "YnVmX3VuaXR0ZXN0X2V4dHJhLlRlc3RYbWxNZXNzYWdlGGYgASgJOkUKEGV4" + 
+          "dGVuc2lvbl9udW1iZXISJy5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0" + 
+          "WG1sTWVzc2FnZRhnIAMoBUICEAE6bgoRZXh0ZW5zaW9uX21lc3NhZ2USJy5w" + 
+          "cm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sTWVzc2FnZRjHASABKAsy" + 
+          "KS5wcm90b2J1Zl91bml0dGVzdF9leHRyYS5UZXN0WG1sRXh0ZW5zaW9uQkxI" + 
+          "AcI+RwohR29vZ2xlLlByb3RvY29sQnVmZmVycy5UZXN0UHJvdG9zEiJVbml0" + 
+          "VGVzdFhtbFNlcmlhbGl6ZXJUZXN0UHJvdG9GaWxl");
       pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
         descriptor = root;
         internal__static_protobuf_unittest_extra_TestXmlChild__Descriptor = Descriptor.MessageTypes[0];
@@ -83,7 +87,11 @@ namespace Google.ProtocolBuffers.TestProtos {
         internal__static_protobuf_unittest_extra_TestXmlNoFields__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields, global::Google.ProtocolBuffers.TestProtos.TestXmlNoFields.Builder>(internal__static_protobuf_unittest_extra_TestXmlNoFields__Descriptor,
                 new string[] { });
-        internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor = Descriptor.MessageTypes[2];
+        internal__static_protobuf_unittest_extra_TestXmlRescursive__Descriptor = Descriptor.MessageTypes[2];
+        internal__static_protobuf_unittest_extra_TestXmlRescursive__FieldAccessorTable = 
+            new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive, global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Builder>(internal__static_protobuf_unittest_extra_TestXmlRescursive__Descriptor,
+                new string[] { "Child", });
+        internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor = Descriptor.MessageTypes[3];
         internal__static_protobuf_unittest_extra_TestXmlMessage__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Builder>(internal__static_protobuf_unittest_extra_TestXmlMessage__Descriptor,
                 new string[] { "Number", "Numbers", "Text", "Textlines", "Valid", "Child", "Children", });
@@ -91,7 +99,7 @@ namespace Google.ProtocolBuffers.TestProtos {
         internal__static_protobuf_unittest_extra_TestXmlMessage_Children__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children, global::Google.ProtocolBuffers.TestProtos.TestXmlMessage.Types.Children.Builder>(internal__static_protobuf_unittest_extra_TestXmlMessage_Children__Descriptor,
                 new string[] { "Options", "Binary", });
-        internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor = Descriptor.MessageTypes[3];
+        internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor = Descriptor.MessageTypes[4];
         internal__static_protobuf_unittest_extra_TestXmlExtension__FieldAccessorTable = 
             new pb::FieldAccess.FieldAccessorTable<global::Google.ProtocolBuffers.TestProtos.TestXmlExtension, global::Google.ProtocolBuffers.TestProtos.TestXmlExtension.Builder>(internal__static_protobuf_unittest_extra_TestXmlExtension__Descriptor,
                 new string[] { "Number", });
@@ -631,6 +639,268 @@ namespace Google.ProtocolBuffers.TestProtos {
     }
   }
   
+  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
+  public sealed partial class TestXmlRescursive : pb::GeneratedMessage<TestXmlRescursive, TestXmlRescursive.Builder> {
+    private static readonly TestXmlRescursive defaultInstance = new Builder().BuildPartial();
+    private static readonly string[] _testXmlRescursiveFieldNames = new string[] { "child" };
+    private static readonly uint[] _testXmlRescursiveFieldTags = new uint[] { 10 };
+    public static TestXmlRescursive DefaultInstance {
+      get { return defaultInstance; }
+    }
+    
+    public override TestXmlRescursive DefaultInstanceForType {
+      get { return defaultInstance; }
+    }
+    
+    protected override TestXmlRescursive ThisMessage {
+      get { return this; }
+    }
+    
+    public static pbd::MessageDescriptor Descriptor {
+      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlRescursive__Descriptor; }
+    }
+    
+    protected override pb::FieldAccess.FieldAccessorTable<TestXmlRescursive, TestXmlRescursive.Builder> InternalFieldAccessors {
+      get { return global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.internal__static_protobuf_unittest_extra_TestXmlRescursive__FieldAccessorTable; }
+    }
+    
+    public const int ChildFieldNumber = 1;
+    private bool hasChild;
+    private global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance;
+    public bool HasChild {
+      get { return hasChild; }
+    }
+    public global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive Child {
+      get { return child_; }
+    }
+    
+    public override bool IsInitialized {
+      get {
+        return true;
+      }
+    }
+    
+    public override void WriteTo(pb::ICodedOutputStream output) {
+      int size = SerializedSize;
+      string[] field_names = _testXmlRescursiveFieldNames;
+      if (hasChild) {
+        output.WriteMessage(1, field_names[0], Child);
+      }
+      UnknownFields.WriteTo(output);
+    }
+    
+    private int memoizedSerializedSize = -1;
+    public override int SerializedSize {
+      get {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+        
+        size = 0;
+        if (hasChild) {
+          size += pb::CodedOutputStream.ComputeMessageSize(1, Child);
+        }
+        size += UnknownFields.SerializedSize;
+        memoizedSerializedSize = size;
+        return size;
+      }
+    }
+    
+    public static TestXmlRescursive ParseFrom(pb::ByteString data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(byte[] data) {
+      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(global::System.IO.Stream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseDelimitedFrom(global::System.IO.Stream input) {
+      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
+    }
+    public static TestXmlRescursive ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
+      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(pb::ICodedInputStream input) {
+      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
+    }
+    public static TestXmlRescursive ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
+    }
+    public static Builder CreateBuilder() { return new Builder(); }
+    public override Builder ToBuilder() { return CreateBuilder(this); }
+    public override Builder CreateBuilderForType() { return new Builder(); }
+    public static Builder CreateBuilder(TestXmlRescursive prototype) {
+      return (Builder) new Builder().MergeFrom(prototype);
+    }
+    
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
+    public sealed partial class Builder : pb::GeneratedBuilder<TestXmlRescursive, Builder> {
+      protected override Builder ThisBuilder {
+        get { return this; }
+      }
+      public Builder() {}
+      
+      TestXmlRescursive result = new TestXmlRescursive();
+      
+      protected override TestXmlRescursive MessageBeingBuilt {
+        get { return result; }
+      }
+      
+      public override Builder Clear() {
+        result = new TestXmlRescursive();
+        return this;
+      }
+      
+      public override Builder Clone() {
+        return new Builder().MergeFrom(result);
+      }
+      
+      public override pbd::MessageDescriptor DescriptorForType {
+        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Descriptor; }
+      }
+      
+      public override TestXmlRescursive DefaultInstanceForType {
+        get { return global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance; }
+      }
+      
+      public override TestXmlRescursive BuildPartial() {
+        if (result == null) {
+          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
+        }
+        TestXmlRescursive returnMe = result;
+        result = null;
+        return returnMe;
+      }
+      
+      public override Builder MergeFrom(pb::IMessage other) {
+        if (other is TestXmlRescursive) {
+          return MergeFrom((TestXmlRescursive) other);
+        } else {
+          base.MergeFrom(other);
+          return this;
+        }
+      }
+      
+      public override Builder MergeFrom(TestXmlRescursive other) {
+        if (other == global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance) return this;
+        if (other.HasChild) {
+          MergeChild(other.Child);
+        }
+        this.MergeUnknownFields(other.UnknownFields);
+        return this;
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input) {
+        return MergeFrom(input, pb::ExtensionRegistry.Empty);
+      }
+      
+      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
+        pb::UnknownFieldSet.Builder unknownFields = null;
+        uint tag;
+        string field_name;
+        while (input.ReadTag(out tag, out field_name)) {
+          if(tag == 0 && field_name != null) {
+            int field_ordinal = global::System.Array.BinarySearch(_testXmlRescursiveFieldNames, field_name, global::System.StringComparer.Ordinal);
+            if(field_ordinal >= 0)
+              tag = _testXmlRescursiveFieldTags[field_ordinal];
+            else {
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              continue;
+            }
+          }
+          switch (tag) {
+            case 0: {
+              throw pb::InvalidProtocolBufferException.InvalidTag();
+            }
+            default: {
+              if (pb::WireFormat.IsEndGroupTag(tag)) {
+                if (unknownFields != null) {
+                  this.UnknownFields = unknownFields.Build();
+                }
+                return this;
+              }
+              if (unknownFields == null) {
+                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
+              }
+              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
+              break;
+            }
+            case 10: {
+              global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.CreateBuilder();
+              if (result.hasChild) {
+                subBuilder.MergeFrom(Child);
+              }
+              input.ReadMessage(subBuilder, extensionRegistry);
+              Child = subBuilder.BuildPartial();
+              break;
+            }
+          }
+        }
+        
+        if (unknownFields != null) {
+          this.UnknownFields = unknownFields.Build();
+        }
+        return this;
+      }
+      
+      
+      public bool HasChild {
+       get { return result.hasChild; }
+      }
+      public global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive Child {
+        get { return result.Child; }
+        set { SetChild(value); }
+      }
+      public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        result.hasChild = true;
+        result.child_ = value;
+        return this;
+      }
+      public Builder SetChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.Builder builderForValue) {
+        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
+        result.hasChild = true;
+        result.child_ = builderForValue.Build();
+        return this;
+      }
+      public Builder MergeChild(global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive value) {
+        pb::ThrowHelper.ThrowIfNull(value, "value");
+        if (result.hasChild &&
+            result.child_ != global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance) {
+            result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.CreateBuilder(result.child_).MergeFrom(value).BuildPartial();
+        } else {
+          result.child_ = value;
+        }
+        result.hasChild = true;
+        return this;
+      }
+      public Builder ClearChild() {
+        result.hasChild = false;
+        result.child_ = global::Google.ProtocolBuffers.TestProtos.TestXmlRescursive.DefaultInstance;
+        return this;
+      }
+    }
+    static TestXmlRescursive() {
+      object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.UnitTestXmlSerializerTestProtoFile.Descriptor, null);
+    }
+  }
+  
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
   [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
   [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]

+ 9 - 0
src/ProtocolBuffers.Test/TestWriterFormatJson.cs

@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using System.Text;
 using Google.ProtocolBuffers.Serialization;
 using NUnit.Framework;
 using Google.ProtocolBuffers.TestProtos;
@@ -336,6 +337,14 @@ namespace Google.ProtocolBuffers
             Assert.AreEqual(3, ordinal);
             Assert.AreEqual(3, builder.TextlinesCount);
         }
+        [Test,ExpectedException(typeof(InvalidProtocolBufferException))]
+        public void TestRecursiveLimit()
+        {
+            StringBuilder sb = new StringBuilder(8192);
+            for (int i = 0; i < 80; i++)
+                sb.Append("{\"child\":");
+            TestXmlRescursive msg = TestXmlRescursive.ParseFromJson(sb.ToString());
+        }
         [Test, ExpectedException(typeof(FormatException))]
         public void FailWithEmptyText()
         {

+ 8 - 0
src/ProtocolBuffers.Test/TestWriterFormatXml.cs

@@ -324,5 +324,13 @@ namespace Google.ProtocolBuffers
             TestXmlMessage copy = rdr.Merge(TestXmlMessage.CreateBuilder(), registry).Build();
             Assert.AreEqual(message, copy);
         }
+        [Test, ExpectedException(typeof(InvalidProtocolBufferException))]
+        public void TestRecursiveLimit()
+        {
+            StringBuilder sb = new StringBuilder(8192);
+            for (int i = 0; i < 80; i++)
+                sb.Append("<child>");
+            TestXmlRescursive msg = TestXmlRescursive.ParseFromXml("child", XmlReader.Create(new StringReader(sb.ToString())));
+        }
     }
 }

+ 27 - 4
src/ProtocolBuffers/Serialization/AbstractReader.cs

@@ -12,6 +12,9 @@ namespace Google.ProtocolBuffers.Serialization
     /// </summary>
     public abstract class AbstractReader : ICodedInputStream
     {
+        const int MaxDepth = CodedInputStream.DefaultRecursionLimit;
+        protected int _depth;
+
         /// <summary>
         /// Merges the contents of stream into the provided message builder
         /// </summary>
@@ -330,13 +333,23 @@ namespace Google.ProtocolBuffers.Serialization
         { return Read(ref value); }
 
         void ICodedInputStream.ReadGroup(int fieldNumber, IBuilderLite builder, ExtensionRegistry extensionRegistry)
-        { ReadGroup(builder, extensionRegistry); }
+        {
+            if (_depth++ > MaxDepth)
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            ReadGroup(builder, extensionRegistry);
+            _depth--;
+        }
 
         void ICodedInputStream.ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
         { throw new NotSupportedException(); }
 
         void ICodedInputStream.ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
-        { ReadMessage(builder, extensionRegistry); }
+        {
+            if (_depth++ > MaxDepth)
+                throw InvalidProtocolBufferException.RecursionLimitExceeded(); 
+            ReadMessage(builder, extensionRegistry);
+            _depth--;
+        }
 
         bool ICodedInputStream.ReadBytes(ref ByteString value)
         { return Read(ref value); }
@@ -439,10 +452,20 @@ namespace Google.ProtocolBuffers.Serialization
         }
 
         void ICodedInputStream.ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry)
-        { ReadMessageArray(fieldName, list, messageType, registry); }
+        {
+            if (_depth++ > MaxDepth)
+                throw InvalidProtocolBufferException.RecursionLimitExceeded(); 
+            ReadMessageArray(fieldName, list, messageType, registry);
+            _depth--;
+        }
 
         void ICodedInputStream.ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType, ExtensionRegistry registry)
-        { ReadGroupArray(fieldName, list, messageType, registry); }
+        {
+            if (_depth++ > MaxDepth)
+                throw InvalidProtocolBufferException.RecursionLimitExceeded();
+            ReadGroupArray(fieldName, list, messageType, registry);
+            _depth--;
+        }
 
         bool ICodedInputStream.ReadPrimitiveField(FieldType fieldType, ref object value)
         { return ReadField(fieldType, ref value); }

+ 11 - 3
src/ProtocolBuffers/Serialization/DictionaryWriter.cs

@@ -15,7 +15,7 @@ namespace Google.ProtocolBuffers.Serialization
         /// Constructs a writer using a new dictionary
         /// </summary>
         public DictionaryWriter()
-            : this(new Dictionary<string,object>())
+            : this(new Dictionary<string,object>(StringComparer.Ordinal))
         { }
 
         /// <summary>
@@ -27,6 +27,14 @@ namespace Google.ProtocolBuffers.Serialization
             _output = output;
         }
 
+        /// <summary>
+        /// Creates the dictionary instance for a child message.
+        /// </summary>
+        protected virtual DictionaryWriter Create()
+        {
+            return new DictionaryWriter();
+        }
+
         /// <summary>
         /// Accesses the dictionary that is backing this writer
         /// </summary>
@@ -119,7 +127,7 @@ namespace Google.ProtocolBuffers.Serialization
         /// </summary>
         protected override void WriteMessageOrGroup(string field, IMessageLite message)
         {
-            DictionaryWriter writer = new DictionaryWriter();
+            DictionaryWriter writer = Create();
             writer.WriteMessage(message);
 
             _output[field] = writer.ToDictionary();
@@ -146,7 +154,7 @@ namespace Google.ProtocolBuffers.Serialization
                     case FieldType.Group:
                     case FieldType.Message:
                         {
-                            DictionaryWriter writer = new DictionaryWriter();
+                            DictionaryWriter writer = Create();
                             writer.WriteMessage((IMessageLite)o);
                             objects.Add(writer.ToDictionary());
                         }

+ 5 - 1
src/ProtocolBuffers/Serialization/XmlFormatReader.cs

@@ -72,7 +72,11 @@ namespace Google.ProtocolBuffers.Serialization
 
         private XmlFormatReader CloneWith(XmlReader rdr)
         {
-            return new XmlFormatReader(rdr).SetOptions(Options);
+            XmlFormatReader copy = new XmlFormatReader(rdr).SetOptions(Options);
+            copy._rootElementName = _rootElementName;
+            copy._depth = _depth;
+            return copy;
+
         }
         private void NextElement()
         {