Skip to content

Commit 275c1e5

Browse files
authored
SkipBlockAlignmentPadding must be executed for all entries (#74396)
1 parent bd4bea6 commit 275c1e5

File tree

5 files changed

+142
-2
lines changed

5 files changed

+142
-2
lines changed

src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarReader.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,10 @@ internal void AdvanceDataStreamIfNeeded()
225225
{
226226
long bytesToSkip = _previouslyReadEntry._header._size - dataStream.Position;
227227
TarHelpers.AdvanceStream(_archiveStream, bytesToSkip);
228-
TarHelpers.SkipBlockAlignmentPadding(_archiveStream, _previouslyReadEntry._header._size);
229228
dataStream.HasReachedEnd = true; // Now the pointer is beyond the limit, so any read attempts should throw
230229
}
231230
}
231+
TarHelpers.SkipBlockAlignmentPadding(_archiveStream, _previouslyReadEntry._header._size);
232232
}
233233
}
234234

@@ -267,10 +267,10 @@ internal async ValueTask AdvanceDataStreamIfNeededAsync(CancellationToken cancel
267267
{
268268
long bytesToSkip = _previouslyReadEntry._header._size - dataStream.Position;
269269
await TarHelpers.AdvanceStreamAsync(_archiveStream, bytesToSkip, cancellationToken).ConfigureAwait(false);
270-
await TarHelpers.SkipBlockAlignmentPaddingAsync(_archiveStream, _previouslyReadEntry._header._size, cancellationToken).ConfigureAwait(false);
271270
dataStream.HasReachedEnd = true; // Now the pointer is beyond the limit, so any read attempts should throw
272271
}
273272
}
273+
await TarHelpers.SkipBlockAlignmentPaddingAsync(_archiveStream, _previouslyReadEntry._header._size, cancellationToken).ConfigureAwait(false);
274274
}
275275
}
276276

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.IO;
6+
using System.IO.Compression;
67
using System.Linq;
78
using Xunit;
89

@@ -145,5 +146,36 @@ private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entry
145146

146147
Assert.Equal(2, Directory.GetFileSystemEntries(baseDir).Count());
147148
}
149+
150+
[Theory]
151+
[InlineData(512)]
152+
[InlineData(512 + 1)]
153+
[InlineData(512 + 512 - 1)]
154+
public void Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries(int contentSize)
155+
{
156+
byte[] fileContents = new byte[contentSize];
157+
Array.Fill<byte>(fileContents, 0x1);
158+
159+
using var archive = new MemoryStream();
160+
using (var compressor = new GZipStream(archive, CompressionMode.Compress, leaveOpen: true))
161+
{
162+
using var writer = new TarWriter(compressor);
163+
var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file");
164+
entry1.DataStream = new MemoryStream(fileContents);
165+
writer.WriteEntry(entry1);
166+
167+
var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file");
168+
writer.WriteEntry(entry2);
169+
}
170+
171+
archive.Position = 0;
172+
using var decompressor = new GZipStream(archive, CompressionMode.Decompress);
173+
using var reader = new TarReader(decompressor);
174+
175+
using TempDirectory destination = new TempDirectory();
176+
TarFile.ExtractToDirectory(decompressor, destination.Path, overwriteFiles: true);
177+
178+
Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count());
179+
}
148180
}
149181
}

src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Collections.Generic;
55
using System.IO;
6+
using System.IO.Compression;
67
using System.Linq;
78
using System.Threading;
89
using System.Threading.Tasks;
@@ -174,5 +175,36 @@ private async Task Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEnt
174175
}
175176
}
176177
}
178+
179+
[Theory]
180+
[InlineData(512)]
181+
[InlineData(512 + 1)]
182+
[InlineData(512 + 512 - 1)]
183+
public async Task Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize)
184+
{
185+
byte[] fileContents = new byte[contentSize];
186+
Array.Fill<byte>(fileContents, 0x1);
187+
188+
using var archive = new MemoryStream();
189+
using (var compressor = new GZipStream(archive, CompressionMode.Compress, leaveOpen: true))
190+
{
191+
using var writer = new TarWriter(compressor);
192+
var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file");
193+
entry1.DataStream = new MemoryStream(fileContents);
194+
await writer.WriteEntryAsync(entry1);
195+
196+
var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file");
197+
await writer.WriteEntryAsync(entry2);
198+
}
199+
200+
archive.Position = 0;
201+
using var decompressor = new GZipStream(archive, CompressionMode.Decompress);
202+
using var reader = new TarReader(decompressor);
203+
204+
using TempDirectory destination = new TempDirectory();
205+
await TarFile.ExtractToDirectoryAsync(decompressor, destination.Path, overwriteFiles: true);
206+
207+
Assert.Equal(2, Directory.GetFileSystemEntries(destination.Path, "*", SearchOption.AllDirectories).Count());
208+
}
177209
}
178210
}

src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,5 +250,43 @@ public void GetNextEntry_UnseekableArchive_ReplaceDataStream_ExcludeFromDisposin
250250
Assert.Equal("Substituted", streamReader.ReadLine());
251251
}
252252
}
253+
254+
[Theory]
255+
[InlineData(512)]
256+
[InlineData(512 + 1)]
257+
[InlineData(512 + 512 - 1)]
258+
public void BlockAlignmentPadding_DoesNotAffectNextEntries(int contentSize)
259+
{
260+
byte[] fileContents = new byte[contentSize];
261+
Array.Fill<byte>(fileContents, 0x1);
262+
263+
using var archive = new MemoryStream();
264+
using (var writer = new TarWriter(archive, leaveOpen: true))
265+
{
266+
var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file");
267+
entry1.DataStream = new MemoryStream(fileContents);
268+
writer.WriteEntry(entry1);
269+
270+
var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file");
271+
writer.WriteEntry(entry2);
272+
}
273+
274+
archive.Position = 0;
275+
using var unseekable = new WrappedStream(archive, archive.CanRead, archive.CanWrite, canSeek: false);
276+
using var reader = new TarReader(unseekable);
277+
278+
TarEntry e = reader.GetNextEntry();
279+
Assert.Equal(contentSize, e.Length);
280+
281+
byte[] buffer = new byte[contentSize];
282+
while (e.DataStream.Read(buffer) > 0) ;
283+
AssertExtensions.SequenceEqual(fileContents, buffer);
284+
285+
e = reader.GetNextEntry();
286+
Assert.Equal(0, e.Length);
287+
288+
e = reader.GetNextEntry();
289+
Assert.Null(e);
290+
}
253291
}
254292
}

src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,5 +288,43 @@ public async Task GetNextEntry_UnseekableArchive_ReplaceDataStream_ExcludeFromDi
288288
}
289289
}
290290
}
291+
292+
[Theory]
293+
[InlineData(512)]
294+
[InlineData(512 + 1)]
295+
[InlineData(512 + 512 - 1)]
296+
public async Task BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize)
297+
{
298+
byte[] fileContents = new byte[contentSize];
299+
Array.Fill<byte>(fileContents, 0x1);
300+
301+
using var archive = new MemoryStream();
302+
using (var writer = new TarWriter(archive, leaveOpen: true))
303+
{
304+
var entry1 = new PaxTarEntry(TarEntryType.RegularFile, "file");
305+
entry1.DataStream = new MemoryStream(fileContents);
306+
await writer.WriteEntryAsync(entry1);
307+
308+
var entry2 = new PaxTarEntry(TarEntryType.RegularFile, "next-file");
309+
await writer.WriteEntryAsync(entry2);
310+
}
311+
312+
archive.Position = 0;
313+
using var unseekable = new WrappedStream(archive, archive.CanRead, archive.CanWrite, canSeek: false);
314+
using var reader = new TarReader(unseekable);
315+
316+
TarEntry e = await reader.GetNextEntryAsync();
317+
Assert.Equal(contentSize, e.Length);
318+
319+
byte[] buffer = new byte[contentSize];
320+
while (e.DataStream.Read(buffer) > 0) ;
321+
AssertExtensions.SequenceEqual(fileContents, buffer);
322+
323+
e = await reader.GetNextEntryAsync();
324+
Assert.Equal(0, e.Length);
325+
326+
e = await reader.GetNextEntryAsync();
327+
Assert.Null(e);
328+
}
291329
}
292330
}

0 commit comments

Comments
 (0)