Skip to content

Possible memory leak in IIS when StartupHook initializes #59524

@leeriorio

Description

@leeriorio

I was analyzing ASP.NET Core using Svace static analyer. It has found HANDLE_LEAK category error with the following message:

new PhysicalFileProvider(contentRoot) is not disposed at the end of the function

in method Initialize(). Here's the source code:

public static void Initialize()
{
if (!NativeMethods.IsAspNetCoreModuleLoaded())
{
// This means someone set the startup hook for Microsoft.AspNetCore.Server.IIS
// but are not running inprocess. Return at this point.
return;
}
var detailedErrors = Environment.GetEnvironmentVariable("ASPNETCORE_DETAILEDERRORS");
var enableStartupErrorPage = detailedErrors?.Equals("1", StringComparison.OrdinalIgnoreCase) ?? false;
enableStartupErrorPage |= detailedErrors?.Equals("true", StringComparison.OrdinalIgnoreCase) ?? false;
var aspnetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
enableStartupErrorPage |= aspnetCoreEnvironment?.Equals("Development", StringComparison.OrdinalIgnoreCase) ?? false;
var dotnetEnvironment = Environment.GetEnvironmentVariable("DOTNET_ENVIRONMENT");
enableStartupErrorPage |= dotnetEnvironment?.Equals("Development", StringComparison.OrdinalIgnoreCase) ?? false;
if (!enableStartupErrorPage)
{
// Not running in development or detailed errors aren't enabled
return;
}
AppDomain.CurrentDomain.UnhandledException += (sender, eventArgs) =>
{
var exception = (Exception)eventArgs.ExceptionObject;
// Get the content root from IIS.
var iisConfigData = NativeMethods.HttpGetApplicationProperties();
var contentRoot = iisConfigData.pwzFullApplicationPath.TrimEnd(Path.DirectorySeparatorChar);
var model = ErrorPageModelBuilder.CreateErrorPageModel(
new PhysicalFileProvider(contentRoot),
logger: null,
showDetailedErrors: true,
exception);
var errorPage = new ErrorPage(model);
var stream = new MemoryStream();
// Never will go async because we are writing to a memory stream.
errorPage.ExecuteAsync(stream).GetAwaiter().GetResult();
// Get the raw content and set the error page.
stream.Position = 0;
var content = stream.ToArray();
NativeMethods.HttpSetStartupErrorPageContent(content);
};
}

I know, that it seems to be minor leak because of IIS startup specific, but how about to add using statement to ensure proper disposal?

    using var fileProvider = new PhysicalFileProvider(contentRoot);

    var model = ErrorPageModelBuilder.CreateErrorPageModel(
        fileProvider,
        logger: null,
        showDetailedErrors: true,
        exception);

Found by Linux Verification Center (linuxtesting.org) with SVACE.

Metadata

Metadata

Assignees

Labels

area-networkingIncludes servers, yarp, json patch, bedrock, websockets, http client factory, and http abstractions

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions