Repository: dotnet/runtime
File: src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs (C#)

Code before:
                throw new ArgumentException(SR.Format(SR.net_invalid_enum, "EncryptionPolicy"), nameof(policy));
            }

            Interop.SspiCli.SCH_CREDENTIALS credential = default;
            credential.dwVersion = Interop.SspiCli.SCH_CREDENTIALS.CurrentVersion;
            credential.dwFlags = flags;

            if (certificate != null)
            {
                credential.cCreds = 1;
                Span<IntPtr> certificates = stackalloc IntPtr[1];
                certificates[0] = certificate.Handle;
                fixed (void* ptr = &certificates[0])
                {
                    credential.paCred = ptr;
                }
            }

            if (NetEventSource.IsEnabled) NetEventSource.Info($"flags=({flags}), ProtocolFlags=({protocolFlags}), EncryptionPolicy={policy}");

            if (protocolFlags != 0)
            {
                // If we were asked to do specific protocol we need to fill TLS_PARAMETERS.
                Interop.SspiCli.TLS_PARAMETERS tlsParameters = default;
                tlsParameters.grbitDisabledProtocols = (uint)protocolFlags ^ uint.MaxValue;

                credential.cTlsParameters = 1;
                credential.pTlsParameters = &tlsParameters;
            }

            return AcquireCredentialsHandle(direction, &credential);
        }

        internal static byte[]? GetNegotiatedApplicationProtocol(SafeDeleteContext context)
        {
            Interop.SecPkgContext_ApplicationProtocol alpnContext = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPISecureChannel, context, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL, ref alpnContext);

            // Check if the context returned is alpn data, with successful negotiation.
            if (success &&
                alpnContext.ProtoNegoExt == Interop.ApplicationProtocolNegotiationExt.ALPN &&
                alpnContext.ProtoNegoStatus == Interop.ApplicationProtocolNegotiationStatus.Success)
            {
                return alpnContext.Protocol;
            }

            return null;
        }

        public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteSslContext securityContext, ReadOnlyMemory<byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
        {

Review comment (security):
This `credential` is storing a pointer to something on the stack.  I assume that whatever AcquireCredentialsHandle returns doesn't expect that to still be alive?

Code after:

            Interop.SspiCli.SCH_CREDENTIALS credential = default;
            credential.dwVersion = Interop.SspiCli.SCH_CREDENTIALS.CurrentVersion;
            credential.dwFlags = flags;

            IntPtr certificateHandle = IntPtr.Zero;
            if (certificate != null)
            {
                credential.cCreds = 1;
                certificateHandle = certificate.Handle;
                credential.paCred = &certificateHandle;
            }

            if (NetEventSource.IsEnabled) NetEventSource.Info($"flags=({flags}), ProtocolFlags=({protocolFlags}), EncryptionPolicy={policy}");

            if (protocolFlags != 0)
            {
                // If we were asked to do specific protocol we need to fill TLS_PARAMETERS.
                Interop.SspiCli.TLS_PARAMETERS tlsParameters = default;
                tlsParameters.grbitDisabledProtocols = (uint)protocolFlags ^ uint.MaxValue;

                credential.cTlsParameters = 1;
                credential.pTlsParameters = &tlsParameters;
            }

            return AcquireCredentialsHandle(direction, &credential);
        }

        internal static byte[]? GetNegotiatedApplicationProtocol(SafeDeleteContext context)
        {
            Interop.SecPkgContext_ApplicationProtocol alpnContext = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPISecureChannel, context, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_APPLICATION_PROTOCOL, ref alpnContext);

            // Check if the context returned is alpn data, with successful negotiation.
            if (success &&
                alpnContext.ProtoNegoExt == Interop.ApplicationProtocolNegotiationExt.ALPN &&
                alpnContext.ProtoNegoStatus == Interop.ApplicationProtocolNegotiationStatus.Success)
            {
                return alpnContext.Protocol;
            }

            return null;
        }

        public static unsafe SecurityStatusPal EncryptMessage(SafeDeleteSslContext securityContext, ReadOnlyMemory<byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
        {
            // Ensure that there is sufficient space for the message output.
            int bufferSizeNeeded;
            try
            {
                bufferSizeNeeded = checked(input.Length + headerSize + trailerSize);