Skip to content
Browse files

Merge pull request #889 from grumpydev/MultipartLimit-518

Multipart limit 518
  • Loading branch information...
2 parents 3f38b72 + 03e6c00 commit 7cf2d88041f331e0e7efdfc733f10318ae8bc7ee @thecodejunkie thecodejunkie committed Jan 4, 2013
View
14 src/Nancy.Tests/Unit/HttpMultipartFixture.cs
@@ -163,6 +163,20 @@ public void If_the_stream_ends_with_carriage_return_characters_it_should_not_aff
actual.ShouldEqual(expected);
}
+ [Fact]
+ public void Should_limit_the_number_of_boundaries()
+ {
+ // Given
+ var stream = BuildInputStream(null, StaticConfiguration.RequestQueryFormMultipartLimit + 10);
+ var multipart = new HttpMultipart(stream, Boundary);
+
+ // When
+ var boundaries = multipart.GetBoundaries();
+
+ // Then
+ boundaries.Count().ShouldEqual(StaticConfiguration.RequestQueryFormMultipartLimit);
+ }
+
//
private static HttpMultipartSubStream BuildInputStream(string padding, int numberOfBoundaries)
{
View
56 src/Nancy.Tests/Unit/RequestFixture.cs
@@ -532,6 +532,62 @@ public void Should_preserve_all_values_when_multiple_are_posted_using_same_name_
((string)request.Form.age).ShouldEqual("32,42,52");
}
+ [Fact]
+ public void Should_limit_the_amount_of_form_fields_parsed()
+ {
+ // Given
+ var sb = new StringBuilder();
+ for (int i = 0; i < StaticConfiguration.RequestQueryFormMultipartLimit + 10; i++)
+ {
+ if (i > 0)
+ {
+ sb.Append('&');
+ }
+
+ sb.AppendFormat("Field{0}=Value{0}", i);
+ }
+ var memory = CreateRequestStream();
+ var writer = new StreamWriter(memory);
+ writer.Write(sb.ToString());
+ writer.Flush();
+ memory.Position = 0;
+
+ var headers =
+ new Dictionary<string, IEnumerable<string>>
+ {
+ { "content-type", new[] { "application/x-www-form-urlencoded" } }
+ };
+
+ // When
+ var request = new Request("POST", "/", headers, memory, "http");
+
+ // Then
+ ((IEnumerable<string>)request.Form.GetDynamicMemberNames()).Count().ShouldEqual(StaticConfiguration.RequestQueryFormMultipartLimit);
+ }
+
+ [Fact]
+ public void Should_limit_the_amount_of_querystring_fields_parsed()
+ {
+ // Given
+ var sb = new StringBuilder();
+ for (int i = 0; i < StaticConfiguration.RequestQueryFormMultipartLimit + 10; i++)
+ {
+ if (i > 0)
+ {
+ sb.Append('&');
+ }
+
+ sb.AppendFormat("Field{0}=Value{0}", i);
+ }
+ var memory = CreateRequestStream();
+
+ // When
+ var request = new Request("GET", "/", new Dictionary<string, IEnumerable<string>>(), memory, "http", sb.ToString());
+
+ // Then
+ ((IEnumerable<string>)request.Query.GetDynamicMemberNames()).Count().ShouldEqual(StaticConfiguration.RequestQueryFormMultipartLimit);
+ }
+
private static RequestStream CreateRequestStream()
{
return CreateRequestStream(new MemoryStream());
View
10 src/Nancy/Extensions/StringExtensions.cs
@@ -65,10 +65,18 @@ public static DynamicDictionary AsQueryDictionary(this string queryString)
{
var coll = HttpUtility.ParseQueryString(queryString);
var ret = new DynamicDictionary();
-
+
+ var found = 0;
foreach (var key in coll.AllKeys.Where(key => key != null))
{
ret[key] = coll[key];
+
+ found++;
+
+ if (found >= StaticConfiguration.RequestQueryFormMultipartLimit)
+ {
+ break;
+ }
}
return ret;
View
5 src/Nancy/HttpMultipart.cs
@@ -47,7 +47,8 @@ private IEnumerable<HttpMultipartSubStream> GetBoundarySubStreams()
var boundarySubStreams = new List<HttpMultipartSubStream>();
var boundaryStart = this.GetNextBoundaryPosition();
- while (MultipartIsNotCompleted(boundaryStart))
+ var found = 0;
+ while (MultipartIsNotCompleted(boundaryStart) && found < StaticConfiguration.RequestQueryFormMultipartLimit)
{
var boundaryEnd = this.GetNextBoundaryPosition();
boundarySubStreams.Add(new HttpMultipartSubStream(
@@ -56,6 +57,8 @@ private IEnumerable<HttpMultipartSubStream> GetBoundarySubStreams()
this.GetActualEndOfBoundary(boundaryEnd)));
boundaryStart = boundaryEnd;
+
+ found++;
}
return boundarySubStreams;
View
9 src/Nancy/StaticConfiguration.cs
@@ -17,12 +17,13 @@ static StaticConfiguration()
{
disableErrorTraces = !(disableCaches = IsRunningDebug);
CaseSensitive = false;
+ RequestQueryFormMultipartLimit = 1000;
}
/// <summary>
/// Gets or sets a value indicating whether Nancy should disable caching
/// </summary>
- [Description("Determins if Nancy should disable the internal caches. This will have an impact on performance and should not be used in production.")]
+ [Description("Determines if Nancy should disable the internal caches. This will have an impact on performance and should not be used in production.")]
public static bool DisableCaches
{
get
@@ -70,6 +71,12 @@ public static bool IsRunningDebug
}
}
+ /// <summary>
+ /// Gets or sets the limit on the number of query string variables, form fields,
+ /// or multipart sections in a request.
+ /// </summary>
+ public static int RequestQueryFormMultipartLimit { get; set; }
+
private static bool GetDebugMode()
{
try

0 comments on commit 7cf2d88

Please sign in to comment.
Something went wrong with that request. Please try again.