Skip to content

Commit d890c2f

Browse files
committed
Issue #60416 - Fix and coverage test
Correction of BufferedReadStream's Position property setter.
1 parent fbd07b2 commit d890c2f

File tree

2 files changed

+73
-3
lines changed

2 files changed

+73
-3
lines changed

src/Http/WebUtilities/src/BufferedReadStream.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ public override long Position
108108
if (innerOffset <= _bufferCount)
109109
{
110110
// Yes, just skip some of the buffered data
111-
_bufferOffset += innerOffset;
112-
_bufferCount -= innerOffset;
111+
_bufferOffset += _bufferCount - innerOffset;
112+
_bufferCount = innerOffset;
113113
}
114114
else
115115
{

src/Http/WebUtilities/test/MultipartReaderTests.cs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ public class MultipartReaderTests
8080
"<!DOCTYPE html><title>Content of a.html.</title>\r\n" +
8181
"\r\n" +
8282
"--9051914041544843365972754266--\r\n";
83-
8483
private const string TwoPartBodyIncompleteBuffer =
8584
"--9051914041544843365972754266\r\n" +
8685
"Content-Disposition: form-data; name=\"text\"\r\n" +
@@ -93,6 +92,26 @@ public class MultipartReaderTests
9392
"Content of a.txt.\r\n" +
9493
"\r\n" +
9594
"--9051914041544843365";
95+
private const string ThreePartBodyWithMixedFiles =
96+
"--9051914041544843365972754266\r\n" +
97+
"Content-Disposition: form-data; name=\"file1\"; filename=\"a.txt\"\r\n" +
98+
"Content-Type: text/plain\r\n" +
99+
"\r\n" +
100+
"Content of a.txt.\r\n" +
101+
"\r\n" +
102+
"--9051914041544843365972754266\r\n" +
103+
"Content-Disposition: form-data; name=\"file2\"; filename=\"a.html\"\r\n" +
104+
"Content-Type: text/html\r\n" +
105+
"\r\n" +
106+
"<!DOCTYPE html><title>Content of a.html.</title>\r\n" +
107+
"\r\n" +
108+
"--9051914041544843365972754266\r\n" +
109+
"Content-Disposition: form-data; name=\"file3\"; filename=\"a.json\"\r\n" +
110+
"Content-Type: application/json\r\n" +
111+
"\r\n" +
112+
"{ \"Text\": \"Content of a.json.\" }\r\n" +
113+
"\r\n" +
114+
"--9051914041544843365972754266--\r\n";
96115

97116
private static MemoryStream MakeStream(string text)
98117
{
@@ -315,6 +334,57 @@ public void MultipartReader_BufferSizeMustBeLargerThanBoundary_Throws()
315334
});
316335
}
317336

337+
[Fact]
338+
public async Task MultipartReader_ReadMultipartBodyWithFilesForDeferredCopy_Success()
339+
{
340+
var stream = MakeStream(ThreePartBodyWithMixedFiles);
341+
var reader = new MultipartReader(Boundary, stream);
342+
343+
var section = await reader.ReadNextSectionAsync();
344+
Assert.NotNull(section);
345+
Assert.Equal(2, section.Headers.Count);
346+
Assert.Equal("form-data; name=\"file1\"; filename=\"a.txt\"", section.Headers["Content-Disposition"][0]);
347+
Assert.Equal("text/plain", section.Headers["Content-Type"][0]);
348+
var stream1 = section.Body;
349+
350+
section = await reader.ReadNextSectionAsync();
351+
Assert.NotNull(section);
352+
Assert.Equal(2, section.Headers.Count);
353+
Assert.Equal("form-data; name=\"file2\"; filename=\"a.html\"", section.Headers["Content-Disposition"][0]);
354+
Assert.Equal("text/html", section.Headers["Content-Type"][0]);
355+
var stream2 = section.Body;
356+
357+
section = await reader.ReadNextSectionAsync();
358+
Assert.NotNull(section);
359+
Assert.Equal(2, section.Headers.Count);
360+
Assert.Equal("form-data; name=\"file3\"; filename=\"a.json\"", section.Headers["Content-Disposition"][0]);
361+
Assert.Equal("application/json", section.Headers["Content-Type"][0]);
362+
var stream3 = section.Body;
363+
364+
Assert.Null(await reader.ReadNextSectionAsync());
365+
366+
Assert.True(stream1.CanSeek);
367+
Assert.Equal(0, stream1.Seek(0, SeekOrigin.Begin));
368+
var buffer = new MemoryStream();
369+
var exception = await Record.ExceptionAsync(() => stream1.CopyToAsync(buffer));
370+
Assert.Null(exception);
371+
Assert.Equal("Content of a.txt.\r\n", Encoding.ASCII.GetString(buffer.ToArray()));
372+
373+
Assert.True(stream2.CanSeek);
374+
Assert.Equal(0, stream2.Seek(0, SeekOrigin.Begin));
375+
buffer = new MemoryStream();
376+
exception = await Record.ExceptionAsync(() => stream2.CopyToAsync(buffer));
377+
Assert.Null(exception);
378+
Assert.Equal("<!DOCTYPE html><title>Content of a.html.</title>\r\n", Encoding.ASCII.GetString(buffer.ToArray()));
379+
380+
Assert.True(stream3.CanSeek);
381+
Assert.Equal(0, stream3.Seek(0, SeekOrigin.Begin));
382+
buffer = new MemoryStream();
383+
exception = await Record.ExceptionAsync(() => stream3.CopyToAsync(buffer));
384+
Assert.Null(exception);
385+
Assert.Equal("{ \"Text\": \"Content of a.json.\" }\r\n", Encoding.ASCII.GetString(buffer.ToArray()));
386+
}
387+
318388
[Fact]
319389
public async Task MultipartReader_TwoPartBodyIncompleteBuffer_TwoSectionsReadSuccessfullyThirdSectionThrows()
320390
{

0 commit comments

Comments
 (0)