@@ -19,18 +19,29 @@ namespace CefSharp
1919 {
2020 private:
2121 MCefRefPtr<CefSelectClientCertificateCallback> _callback;
22- const CefRequestHandler::X509CertificateList& _certificateList;
22+ // Owned copy of the certificates Chromium offered, not a reference to the caller's list.
23+ // That list belongs to CEF for the duration of ClientAdapter::OnSelectClientCertificate,
24+ // and this wrapper deliberately outlives that call - CEF allows Select to be called
25+ // "either in this method or at a later time" - so a reference would dangle the moment
26+ // the handler returns and a deferred Select would read freed memory.
27+ // A ref class cannot hold a std::vector by value, hence the pointer. Copying the vector
28+ // copies the reference-counted CefX509Certificate pointers, and those references are
29+ // what keep the certificates themselves alive.
30+ CefRequestHandler::X509CertificateList* _certificateList;
2331
2432 public:
2533 CefCertificateCallbackWrapper (CefRefPtr<CefSelectClientCertificateCallback>& callback, const CefRequestHandler::X509CertificateList& certificates)
26- : _callback(callback), _certificateList(certificates)
34+ : _callback(callback), _certificateList(new CefRequestHandler::X509CertificateList( certificates) )
2735 {
2836
2937 }
3038
3139 !CefCertificateCallbackWrapper()
3240 {
3341 _callback = nullptr ;
42+
43+ delete _certificateList;
44+ _certificateList = nullptr ;
3445 }
3546
3647 ~CefCertificateCallbackWrapper ()
@@ -53,8 +64,8 @@ namespace CefSharp
5364 auto certThumbprint = cert->Thumbprint ;
5465
5566 std::vector<CefRefPtr<CefX509Certificate>>::const_iterator it =
56- _certificateList. begin ();
57- for (; it != _certificateList. end (); ++it)
67+ _certificateList-> begin ();
68+ for (; it != _certificateList-> end (); ++it)
5869 {
5970 auto bytes ((*it)->GetDEREncoded ());
6071 auto byteSize = bytes->GetSize ();
0 commit comments