Skip to content

Commit cecf76f

Browse files
authored
Merge 4979b64 into 89ead4d
2 parents 89ead4d + 4979b64 commit cecf76f

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

CefSharp.Core.Runtime/Internals/CefCertificateCallbackWrapper.h

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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();

CefSharp.Core.Runtime/Internals/ClientAdapter.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,6 @@ namespace CefSharp
764764
auto browserWrapper = GetBrowserWrapper(browser->GetIdentifier(), browser->IsPopup());
765765

766766
auto list = gcnew X509Certificate2Collection();
767-
// Create a copy of the vector in an attempt to fix #2948
768-
CefRequestHandler::X509CertificateList certs;
769767

770768
std::vector<CefRefPtr<CefX509Certificate> >::const_iterator it =
771769
certificates.begin();
@@ -780,11 +778,11 @@ namespace CefSharp
780778
bytes->GetData(static_cast<void*>(src), byteSize, 0);
781779
auto cert = gcnew X509Certificate2(bufferByte);
782780
list->Add(cert);
783-
784-
certs.push_back(*it);
785781
}
786782

787-
auto callbackWrapper = gcnew CefCertificateCallbackWrapper(callback, certs);
783+
// Passed straight through. The wrapper takes its own reference to each certificate, so
784+
// there is no need to copy the vector here.
785+
auto callbackWrapper = gcnew CefCertificateCallbackWrapper(callback, certificates);
788786

789787
return handler->OnSelectClientCertificate(
790788
_browserControl, browserWrapper, isProxy,

0 commit comments

Comments
 (0)