Skip to content

SafeCertContextHandle is missing a default constructor #43016

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

Closed
MichalStrehovsky opened this issue Oct 4, 2020 · 7 comments
Closed

SafeCertContextHandle is missing a default constructor #43016

MichalStrehovsky opened this issue Oct 4, 2020 · 7 comments

Comments

@MichalStrehovsky
Copy link
Member

This one:

Without that, it cannot be used in return value marshalling because the return value marshaller needs the default constructor to make an instance of one.

Here's an example of a p/invoke that doesn't actually work because of this:

[DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern unsafe SafeCertContextHandle CertCreateCertificateContext(
MsgEncodingType dwCertEncodingType,
void* pbCertEncoded,
int cbCertEncoded);
}

Interop.CertCreateCertificateContext.cs is probably dead code. But I can see that SafeCertContextHandle is actually used as a return value in a number of p/invokes. It should probably be investigated why they're not failing (or why we have no coverage).

Here's a sample standalone example showing the CertCreateCertificateContext p/invoke not actually working (feel free to paste into an empty console app):

using System;
using System.Runtime.InteropServices;

unsafe
{
    Crypt32.CertCreateCertificateContext(0, null, 0);
}

internal static partial class Crypt32
{
    [DllImport("Crypt32", CharSet = CharSet.Unicode, SetLastError = true)]
    internal static extern unsafe SafeCertContextHandle CertCreateCertificateContext(
        int dwCertEncodingType,
        void* pbCertEncoded,
        int cbCertEncoded);
}

internal sealed class SafeCertContextHandle : SafeHandle
{
    internal SafeCertContextHandle(IntPtr handle) :
        base(handle, ownsHandle: true)
    {
    }

    public sealed override bool IsInvalid
    {
        get { return handle == IntPtr.Zero; }
    }

    protected sealed override bool ReleaseHandle()
    {
        //Interop.Crypt32.CertFreeCertificateContext(handle); // CertFreeCertificateContext always returns TRUE so no point in checking.
        SetHandle(IntPtr.Zero);
        return true;
    }
}

The above example will fail with a useless System.MissingMethodException: '.ctor', but that's what interop is complaining about.

@ghost
Copy link

ghost commented Oct 4, 2020

Tagging subscribers to this area: @bartonjs, @vcsjones, @krwq, @jeffhandley
See info in area-owners.md if you want to be subscribed.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Oct 4, 2020
@vcsjones
Copy link
Member

vcsjones commented Oct 4, 2020

Interesting. I'll take a look.

@vcsjones
Copy link
Member

vcsjones commented Oct 4, 2020

Here's what I found.

  1. There are two SafeCertContextHandles because... well I don't know why. There is one in X509 and one in Pkcs. We're looking at the one in Pkcs. The one in X509 does have a default constructor.

    But I can see that SafeCertContextHandle is actually used as a return value in a number of p/invokes

    You're likely seeing usages of the X509 version of SafeCertContextHandle:

    internal class SafeCertContextHandle : SafePointerHandle<SafeCertContextHandle>

  2. The p/invoke CertCreateCertificateContext in Pkcs is indeed unused code an can be removed.

  3. The rest of the usages of the Pkcs SafeCertContextHandle are explicitly constructing it with the IntPtr constructor. It's never used as a return or [Out] from p/invoke.

    IntPtr pCertContext = cert.Handle;
    pCertContext = Interop.Crypt32.CertDuplicateCertificateContext(pCertContext);
    SafeCertContextHandle hCertContext = new SafeCertContextHandle(pCertContext);

@vcsjones
Copy link
Member

vcsjones commented Oct 4, 2020

There are two SafeCertContextHandles

"Can we consolidate them and clean this up? 🤔"

Yeah I think that work is being tracked in #26541. It's a bit tangled up though, I'll see if I can keep chipping away at that cleanup effort.

@MichalStrehovsky
Copy link
Member Author

I don't have a vested interest in the resolution of this - if this is essentially a dup of #26541, we can close this. I hit this when running a tool that eagerly pregenerates p/invoke interop and this hit a bug in the tool where it didn't handle junk input well. I fixed the bug in the tool and filed this because I was already in the middle of yak shaving and didn't want to deal with another yak.

@stephentoub stephentoub removed the untriaged New issue has not been triaged by the area owner label Oct 9, 2020
@stephentoub stephentoub added this to the Future milestone Oct 9, 2020
Copy link
Contributor

Due to lack of recent activity, this issue has been marked as a candidate for backlog cleanup. It will be closed if no further activity occurs within 14 more days. Any new comment (by anyone, not necessarily the author) will undo this process.

This process is part of our issue cleanup automation.

@dotnet-policy-service dotnet-policy-service bot added backlog-cleanup-candidate An inactive issue that has been marked for automated closure. no-recent-activity labels Apr 10, 2025
Copy link
Contributor

This issue will now be closed since it had been marked no-recent-activity but received no further activity in the past 14 days. It is still possible to reopen or comment on the issue, but please note that the issue will be locked if it remains inactive for another 30 days.

@dotnet-policy-service dotnet-policy-service bot removed this from the Future milestone Apr 24, 2025
@github-actions github-actions bot locked and limited conversation to collaborators May 25, 2025
@dotnet-policy-service dotnet-policy-service bot removed no-recent-activity backlog-cleanup-candidate An inactive issue that has been marked for automated closure. labels May 25, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants