8000 Fix FontSource/FontFileStream embedded resource memory leak by h3xds1nz · Pull Request #9948 · dotnet/wpf · GitHub
[go: up one dir, main page]

Skip to content

Fix FontSource/FontFileStream embedded resource memory leak #9948

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 12, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -184,27 +184,27 @@ public UnmanagedMemoryStream GetUnmanagedStream()
{
WebResponse response = WpfWebRequestHelper.CreateRequestAndGetResponse(_fontUri);
fontStream = response.GetResponseStream();
if (String.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
if (string.Equals(response.ContentType, ObfuscatedContentType, StringComparison.Ordinal))
{
// The third parameter makes sure the original stream is closed
// when the deobfuscating stream is disposed.
fontStream = new DeobfuscatingStream(fontStream, _fontUri, false);
}
}

UnmanagedMemoryStream unmanagedStream = fontStream as UnmanagedMemoryStream;

if (unmanagedStream != null)
return unmanagedStream;
// We don't want any memory leaks
// TODO: Remove FinalizableUnmanagedStream once FontFileStream is migrated from C++/CLI.
if (fontStream is UnmanagedMemoryStream unmanagedMemoryStream)
return new FinalizableUnmanagedStream(unmanagedMemoryStream);

// Convert the DeobfuscatingStream to byte[]; add it to our cache, dispose it
bits = StreamToByteArray(fontStream);
lock (s_resourceCache)
{
s_resourceCache.Add(_fontUri, bits, false);
}

fontStream?.Close();
}

lock (s_resourceCache)
{
s_resourceCache.Add(_fontUri, bits, false);
fontStream.Close();
}

return ByteArrayToUnmanagedStream(bits);
Expand Down Expand Up @@ -358,7 +358,7 @@ private Stream GetCompositeFontResourceStream()
Assembly fontResourceAssembly = Assembly.GetExecutingAssembly();
ResourceManager rm = new($"{ReflectionUtils.GetAssemblyPartialName(fontResourceAssembly)}.g", fontResourceAssembly);

return rm?.GetStream($"fonts/{fontFilename}");
return rm.GetStream($"fonts/{fontFilename}");
}

#endregion Private Methods
Expand All @@ -371,6 +371,26 @@ private Stream GetCompositeFontResourceStream()

#region Private Classes

/// <summary>
/// Calls <see cref="UnmanagedMemoryStream.Dispose"/> from the destructor.
/// </summary>
// TODO: Remove this once FontFileStream is migrated from C++/CLI.
private sealed class FinalizableUnmanagedStream : UnmanagedMemoryStream
{
private readonly UnmanagedMemoryStream _unmanaged;

internal unsafe FinalizableUnmanagedStream(UnmanagedMemoryStream unmanagedStream)
{
_unmanaged = unmanagedStream;
Initialize(_unmanaged.PositionPointer, _unmanaged.Length, _unmanaged.Length, FileAccess.Read);
}

~FinalizableUnmanagedStream()
{
_unmanaged.Dispose();
}
}

private class PinnedByteArrayStream : UnmanagedMemoryStream
{
internal PinnedByteArrayStream(byte [] bits)
Expand Down
0