diff --git a/src/Http/WebUtilities/src/FormPipeReader.cs b/src/Http/WebUtilities/src/FormPipeReader.cs index 60f337757b..9cd7e7e35d 100644 --- a/src/Http/WebUtilities/src/FormPipeReader.cs +++ b/src/Http/WebUtilities/src/FormPipeReader.cs @@ -92,7 +92,15 @@ namespace Microsoft.AspNetCore.WebUtilities if (!buffer.IsEmpty) { - ParseFormValues(ref buffer, ref accumulator, readResult.IsCompleted); + try + { + ParseFormValues(ref buffer, ref accumulator, readResult.IsCompleted); + } + catch + { + _pipeReader.AdvanceTo(buffer.Start); + throw; + } } if (readResult.IsCompleted) diff --git a/src/Http/WebUtilities/test/FormPipeReaderTests.cs b/src/Http/WebUtilities/test/FormPipeReaderTests.cs index f0e806aae0..9c973c680d 100644 --- a/src/Http/WebUtilities/test/FormPipeReaderTests.cs +++ b/src/Http/WebUtilities/test/FormPipeReaderTests.cs @@ -94,21 +94,32 @@ namespace Microsoft.AspNetCore.WebUtilities [Fact] public async Task ReadFormAsync_ValueCountLimitExceeded_Throw() { - var bodyPipe = await MakePipeReader("foo=1&baz=2&bar=3&baz=4&baf=5"); + var content = "foo=1&baz=2&bar=3&baz=4&baf=5"; + var bodyPipe = await MakePipeReader(content); var exception = await Assert.ThrowsAsync( () => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueCountLimit = 3 })); Assert.Equal("Form value count limit 3 exceeded.", exception.Message); + + // The body pipe is still readable and has not advanced. + var readResult = await bodyPipe.ReadAsync(); + Assert.Equal(Encoding.UTF8.GetBytes(content), readResult.Buffer.ToArray()); } [Fact] public async Task ReadFormAsync_ValueCountLimitExceededSameKey_Throw() { - var bodyPipe = await MakePipeReader("baz=1&baz=2&baz=3&baz=4"); + var content = "baz=1&baz=2&baz=3&baz=4"; + var bodyPipe = await MakePipeReader(content); var exception = await Assert.ThrowsAsync( () => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueCountLimit = 3 })); Assert.Equal("Form value count limit 3 exceeded.", exception.Message); + + + // The body pipe is still readable and has not advanced. + var readResult = await bodyPipe.ReadAsync(); + Assert.Equal(Encoding.UTF8.GetBytes(content), readResult.Buffer.ToArray()); } [Fact] @@ -127,11 +138,16 @@ namespace Microsoft.AspNetCore.WebUtilities [Fact] public async Task ReadFormAsync_KeyLengthLimitExceeded_Throw() { - var bodyPipe = await MakePipeReader("foo=1&baz12345678=2"); + var content = "foo=1&baz12345678=2"; + var bodyPipe = await MakePipeReader(content); var exception = await Assert.ThrowsAsync( () => ReadFormAsync(new FormPipeReader(bodyPipe) { KeyLengthLimit = 10 })); Assert.Equal("Form key length limit 10 exceeded.", exception.Message); + + // The body pipe is still readable and has not advanced. + var readResult = await bodyPipe.ReadAsync(); + Assert.Equal(Encoding.UTF8.GetBytes(content), readResult.Buffer.ToArray()); } [Fact] @@ -150,11 +166,16 @@ namespace Microsoft.AspNetCore.WebUtilities [Fact] public async Task ReadFormAsync_ValueLengthLimitExceeded_Throw() { - var bodyPipe = await MakePipeReader("foo=1&baz=12345678901"); + var content = "foo=1&baz=12345678901"; + var bodyPipe = await MakePipeReader(content); var exception = await Assert.ThrowsAsync( () => ReadFormAsync(new FormPipeReader(bodyPipe) { ValueLengthLimit = 10 })); Assert.Equal("Form value length limit 10 exceeded.", exception.Message); + + // The body pipe is still readable and has not advanced. + var readResult = await bodyPipe.ReadAsync(); + Assert.Equal(Encoding.UTF8.GetBytes(content), readResult.Buffer.ToArray()); } // https://en.wikipedia.org/wiki/Percent-encoding