Commit 3b70dd78 authored by csharptest's avatar csharptest Committed by rogerk

Added recursion limits to AbstractReader.cs

parent 57fa7fdd
// 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;
}
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()
{
......
......@@ -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())));
}
}
}
......@@ -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); }
......
......@@ -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());
}
......
......@@ -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()
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment