Skip to content

Commit d736df6

Browse files
authored
Fix prefix writing on TarHeaderWrite (#75350)
* 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
1 parent 752cb7e commit d736df6

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,5 +299,61 @@ public void WriteTimestampsBeyondOctalLimit(TarEntryFormat format)
299299
}
300300
}
301301
}
302+
303+
[Theory]
304+
[InlineData(TarEntryFormat.V7)]
305+
// [InlineData(TarEntryFormat.Ustar)] https://github.com/dotnet/runtime/issues/75360
306+
[InlineData(TarEntryFormat.Pax)]
307+
[InlineData(TarEntryFormat.Gnu)]
308+
public void WriteLongName(TarEntryFormat format)
309+
{
310+
string maxPathComponent = new string('a', 255);
311+
WriteLongNameCore(format, maxPathComponent);
312+
313+
maxPathComponent = new string('a', 90) + new string('b', 165);
314+
WriteLongNameCore(format, maxPathComponent);
315+
316+
maxPathComponent = new string('a', 165) + new string('b', 90);
317+
WriteLongNameCore(format, maxPathComponent);
318+
}
319+
320+
private void WriteLongNameCore(TarEntryFormat format, string maxPathComponent)
321+
{
322+
Assert.Equal(255, maxPathComponent.Length);
323+
324+
TarEntry entry;
325+
MemoryStream ms = new();
326+
using (TarWriter writer = new(ms, true))
327+
{
328+
TarEntryType entryType = format == TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile;
329+
entry = InvokeTarEntryCreationConstructor(format, entryType, maxPathComponent);
330+
writer.WriteEntry(entry);
331+
332+
entry = InvokeTarEntryCreationConstructor(format, entryType, Path.Join(maxPathComponent, maxPathComponent));
333+
writer.WriteEntry(entry);
334+
}
335+
336+
ms.Position = 0;
337+
using TarReader reader = new(ms);
338+
339+
entry = reader.GetNextEntry();
340+
string expectedName = GetExpectedNameForFormat(format, maxPathComponent);
341+
Assert.Equal(expectedName, entry.Name);
342+
343+
entry = reader.GetNextEntry();
344+
expectedName = GetExpectedNameForFormat(format, Path.Join(maxPathComponent, maxPathComponent));
345+
Assert.Equal(expectedName, entry.Name);
346+
347+
Assert.Null(reader.GetNextEntry());
348+
349+
string GetExpectedNameForFormat(TarEntryFormat format, string expectedName)
350+
{
351+
if (format is TarEntryFormat.V7) // V7 truncates names at 100 characters.
352+
{
353+
return expectedName.Substring(0, 100);
354+
}
355+
return expectedName;
356+
}
357+
}
302358
}
303359
}

0 commit comments

Comments
 (0)