Repository: dotnet/aspnetcore
File: src/Shared/CertificateGeneration/CertificateManager.cs (C#)

Code before:
            Log.NoValidCertificatesFound();
            try
            {
                Log.CreateDevelopmentCertificateStart();
                isNewCertificate = true;
                certificate = CreateAspNetCoreHttpsDevelopmentCertificate(notBefore, notAfter);
            }
            catch (Exception e)
            {
                if (Log.IsEnabled())
                {
                    Log.CreateDevelopmentCertificateError(e.ToString());
                }
                result = EnsureCertificateResult.ErrorCreatingTheCertificate;
                return result;
            }
            Log.CreateDevelopmentCertificateEnd();

            try
            {
                certificate = SaveCertificate(certificate);
            }
            catch (Exception e)
            {
                Log.SaveCertificateInStoreError(e.ToString());
                certificate?.Dispose();
                result = EnsureCertificateResult.ErrorSavingTheCertificateIntoTheCurrentUserPersonalStore;
                return result;
            }

            if (isInteractive)
            {
                try
                {
                    if (Log.IsEnabled())
                    {
                        Log.CorrectCertificateStateStart(GetDescription(certificate));
                    }
                    CorrectCertificateState(certificate);
                    Log.CorrectCertificateStateEnd();
                }
                catch (Exception e)
                {
                    if (Log.IsEnabled())
                    {
                        Log.CorrectCertificateStateError(e.ToString());
                    }

                    // We don't return early on this type of failure to allow for tooling to
                    // export or trust the certificate even in this situation, as that enables
                    // exporting the certificate to perform any necessary fix with native tooling.

Review comment (suggestion):
@copilot The `certificates` variable contains a list of certificates and should be disposed in all early exit cases. See the use of DisposeCertificates at the bottom of this method.

Code after:
        {
            var excludedCertificates = allCurrentUserCertificates.Concat(allLocalMachineCertificates).Except(filteredCertificates);
            Log.FilteredCertificates(ToCertificateDescription(filteredCertificates));
            Log.ExcludedCertificates(ToCertificateDescription(excludedCertificates));
        }

        // Dispose certificates we're not going to use
        DisposeCertificates(allCurrentUserCertificates.Except(currentUserCertificates));
        DisposeCertificates(allLocalMachineCertificates.Except(localMachineCertificates));

        var certificates = filteredCertificates;

        X509Certificate2? certificate = null;
        var isNewCertificate = false;
        if (certificates.Any())
        {
            certificate = certificates.First();
            var failedToFixCertificateState = false;
            if (isInteractive)
            {
                // Skip this step if the command is not interactive,
                // as we don't want to prompt on first run experience.
                foreach (var candidate in currentUserCertificates)
                {
                    var status = CheckCertificateState(candidate);
                    if (!status.Success)
                    {
                        try
                        {
                            if (Log.IsEnabled())
                            {
                                Log.CorrectCertificateStateStart(GetDescription(candidate));
                            }
                            CorrectCertificateState(candidate);
                            Log.CorrectCertificateStateEnd();
                        }
                        catch (Exception e)
                        {
                            if (Log.IsEnabled())
                            {
                                Log.CorrectCertificateStateError(e.ToString());
                            }
                            result = EnsureCertificateResult.FailedToMakeKeyAccessible;
                            // We don't return early on this type of failure to allow for tooling to
                            // export or trust the certificate even in this situation, as that enables
                            // exporting the certificate to perform any necessary fix with native tooling.
                            failedToFixCertificateState = true;
                        }
                    }
                }
            }