Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 9ac4181

Browse files
authored
Fix Path.GetTempFileName on Windows (#17148)
GetTempFileNameW doesn't return the required length of the buffer; it returns the unique number used in the temporary file name. But the calling code is using that result as a length, resulting in sometimes truncated paths, and sometimes paths that aren't at all related to the original due to state left over in a pooled buffer.
1 parent 1ee83de commit 9ac4181

File tree

2 files changed

+7
-8
lines changed

2 files changed

+7
-8
lines changed

src/mscorlib/shared/System/IO/Path.Windows.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -165,20 +165,15 @@ public static string GetTempFileName()
165165
Span<char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
166166
var builder = new ValueStringBuilder(initialBuffer);
167167

168-
uint result = 0;
169-
while ((result = Interop.Kernel32.GetTempFileNameW(
170-
ref tempPathBuilder.GetPinnableReference(), "tmp", 0, ref builder.GetPinnableReference())) > builder.Capacity)
171-
{
172-
// Reported size is greater than the buffer size. Increase the capacity.
173-
builder.EnsureCapacity(checked((int)result));
174-
}
168+
uint result = Interop.Kernel32.GetTempFileNameW(
169+
ref tempPathBuilder.GetPinnableReference(), "tmp", 0, ref builder.GetPinnableReference());
175170

176171
tempPathBuilder.Dispose();
177172

178173
if (result == 0)
179174
throw Win32Marshal.GetExceptionForLastWin32Error();
180175

181-
builder.Length = (int)result;
176+
builder.Length = builder.RawChars.IndexOf('\0');
182177

183178
string path = PathHelper.Normalize(ref builder);
184179
builder.Dispose();

src/mscorlib/shared/System/Text/ValueStringBuilder.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public int Length
2727
get => _pos;
2828
set
2929
{
30+
Debug.Assert(value >= 0);
3031
Debug.Assert(value <= _chars.Length);
3132
_pos = value;
3233
}
@@ -70,6 +71,9 @@ public override string ToString()
7071
return s;
7172
}
7273

74+
/// <summary>Returns the underlying storage of the builder.</summary>
75+
public Span<char> RawChars => _chars;
76+
7377
/// <summary>
7478
/// Returns a span around the contents of the builder.
7579
/// </summary>

0 commit comments

Comments
 (0)