Skip to content

Commit 66a9136

Browse files
[release/7.0] Fix prefix writing on TarHeaderWrite (#75373)
* Fix buffer too small error on prefix * Add test * Remove var usage * Remove assert * Update src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs * Add more lengths and improve test * Add missing using Co-authored-by: David Cantu <[email protected]>
1 parent 83e16f4 commit 66a9136

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,12 +374,9 @@ private int WritePosixName(Span<byte> buffer)
374374

375375
if (_name.Length > FieldLengths.Name)
376376
{
377-
int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Name);
378-
Span<byte> remaining = prefixBytesLength <= 256 ?
379-
stackalloc byte[prefixBytesLength] :
380-
new byte[prefixBytesLength];
381-
382-
int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name), remaining);
377+
int prefixBytesLength = Math.Min(_name.Length - FieldLengths.Name, FieldLengths.Prefix);
378+
Span<byte> remaining = stackalloc byte[prefixBytesLength];
379+
int encoded = Encoding.ASCII.GetBytes(_name.AsSpan(FieldLengths.Name, prefixBytesLength), remaining);
383380
Debug.Assert(encoded == remaining.Length);
384381

385382
checksum += WriteLeftAlignedBytesAndGetChecksum(remaining, buffer.Slice(FieldLocations.Prefix, FieldLengths.Prefix));

src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs

Lines changed: 53 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.Linq;
67
using Xunit;
78

89
namespace System.Formats.Tar.Tests
@@ -299,5 +300,57 @@ public void WriteTimestampsBeyondOctalLimit(TarEntryFormat format)
299300
}
300301
}
301302
}
303+
304+
[Theory]
305+
[InlineData(TarEntryFormat.V7)]
306+
// [InlineData(TarEntryFormat.Ustar)] https://github.com/dotnet/runtime/issues/75360
307+
[InlineData(TarEntryFormat.Pax)]
308+
[InlineData(TarEntryFormat.Gnu)]
309+
public void WriteLongName(TarEntryFormat format)
310+
{
311+
var r = new Random();
312+
foreach (int length in new[] { 99, 100, 101, 199, 200, 201, 254, 255, 256 })
313+
{
314+
string name = string.Concat(Enumerable.Range(0, length).Select(_ => (char)('a' + r.Next(26))));
315+
WriteLongNameCore(format, name);
316+
}
317+
}
318+
319+
private void WriteLongNameCore(TarEntryFormat format, string maxPathComponent)
320+
{
321+
TarEntry entry;
322+
MemoryStream ms = new();
323+
using (TarWriter writer = new(ms, true))
324+
{
325+
TarEntryType entryType = format == TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile;
326+
entry = InvokeTarEntryCreationConstructor(format, entryType, maxPathComponent);
327+
writer.WriteEntry(entry);
328+
329+
entry = InvokeTarEntryCreationConstructor(format, entryType, Path.Join(maxPathComponent, maxPathComponent));
330+
writer.WriteEntry(entry);
331+
}
332+
333+
ms.Position = 0;
334+
using TarReader reader = new(ms);
335+
336+
entry = reader.GetNextEntry();
337+
string expectedName = GetExpectedNameForFormat(format, maxPathComponent);
338+
Assert.Equal(expectedName, entry.Name);
339+
340+
entry = reader.GetNextEntry();
341+
expectedName = GetExpectedNameForFormat(format, Path.Join(maxPathComponent, maxPathComponent));
342+
Assert.Equal(expectedName, entry.Name);
343+
344+
Assert.Null(reader.GetNextEntry());
345+
346+
string GetExpectedNameForFormat(TarEntryFormat format, string expectedName)
347+
{
348+
if (format is TarEntryFormat.V7 && expectedName.Length > 100) // V7 truncates names at 100 characters.
349+
{
350+
return expectedName.Substring(0, 100);
351+
}
352+
return expectedName;
353+
}
354+
}
302355
}
303356
}

0 commit comments

Comments
 (0)