Skip to content

Commit ed998ea

Browse files
committed
qt: Avoid OpenSSL certstore-related memory leak
- Correctly manage the X509 and X509_STORE objects lifetime.
1 parent 5204598 commit ed998ea

File tree

2 files changed

+25
-23
lines changed

2 files changed

+25
-23
lines changed

src/qt/paymentserver.cpp

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,19 @@ const char* BIP71_MIMETYPE_PAYMENTREQUEST = "application/bitcoin-paymentrequest"
5858
// BIP70 max payment request size in bytes (DoS protection)
5959
const qint64 BIP70_MAX_PAYMENTREQUEST_SIZE = 50000;
6060

61-
X509_STORE* PaymentServer::certStore = NULL;
62-
void PaymentServer::freeCertStore()
61+
struct X509StoreDeleter {
62+
void operator()(X509_STORE* b) {
63+
X509_STORE_free(b);
64+
}
65+
};
66+
67+
struct X509Deleter {
68+
void operator()(X509* b) { X509_free(b); }
69+
};
70+
71+
namespace // Anon namespace
6372
{
64-
if (PaymentServer::certStore != NULL)
65-
{
66-
X509_STORE_free(PaymentServer::certStore);
67-
PaymentServer::certStore = NULL;
68-
}
73+
std::unique_ptr<X509_STORE, X509StoreDeleter> certStore;
6974
}
7075

7176
//
@@ -107,20 +112,15 @@ static void ReportInvalidCertificate(const QSslCertificate& cert)
107112
//
108113
void PaymentServer::LoadRootCAs(X509_STORE* _store)
109114
{
110-
if (PaymentServer::certStore == NULL)
111-
atexit(PaymentServer::freeCertStore);
112-
else
113-
freeCertStore();
114-
115115
// Unit tests mostly use this, to pass in fake root CAs:
116116
if (_store)
117117
{
118-
PaymentServer::certStore = _store;
118+
certStore.reset(_store);
119119
return;
120120
}
121121

122122
// Normal execution, use either -rootcertificates or system certs:
123-
PaymentServer::certStore = X509_STORE_new();
123+
certStore.reset(X509_STORE_new());
124124

125125
// Note: use "-system-" default here so that users can pass -rootcertificates=""
126126
// and get 'I don't like X.509 certificates, don't trust anybody' behavior:
@@ -167,11 +167,11 @@ void PaymentServer::LoadRootCAs(X509_STORE* _store)
167167
QByteArray certData = cert.toDer();
168168
const unsigned char *data = (const unsigned char *)certData.data();
169169

170-
X509* x509 = d2i_X509(0, &data, certData.size());
171-
if (x509 && X509_STORE_add_cert(PaymentServer::certStore, x509))
170+
std::unique_ptr<X509, X509Deleter> x509(d2i_X509(0, &data, certData.size()));
171+
if (x509 && X509_STORE_add_cert(certStore.get(), x509.get()))
172172
{
173-
// Note: X509_STORE_free will free the X509* objects when
174-
// the PaymentServer is destroyed
173+
// Note: X509_STORE increases the reference count to the X509 object,
174+
// we still have to release our reference to it.
175175
++nRootCerts;
176176
}
177177
else
@@ -550,7 +550,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
550550
recipient.paymentRequest = request;
551551
recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo());
552552

553-
request.getMerchant(PaymentServer::certStore, recipient.authenticatedMerchant);
553+
request.getMerchant(certStore.get(), recipient.authenticatedMerchant);
554554

555555
QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo();
556556
QStringList addresses;
@@ -807,3 +807,8 @@ bool PaymentServer::verifyAmount(const CAmount& requestAmount)
807807
}
808808
return fVerified;
809809
}
810+
811+
X509_STORE* PaymentServer::getCertStore()
812+
{
813+
return certStore.get();
814+
}

src/qt/paymentserver.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ class PaymentServer : public QObject
8383
static void LoadRootCAs(X509_STORE* store = NULL);
8484

8585
// Return certificate store
86-
static X509_STORE* getCertStore() { return certStore; }
86+
static X509_STORE* getCertStore();
8787

8888
// OptionsModel is used for getting proxy settings and display unit
8989
void setOptionsModel(OptionsModel *optionsModel);
@@ -140,9 +140,6 @@ private Q_SLOTS:
140140
bool saveURIs; // true during startup
141141
QLocalServer* uriServer;
142142

143-
static X509_STORE* certStore; // Trusted root certificates
144-
static void freeCertStore();
145-
146143
QNetworkAccessManager* netManager; // Used to fetch payment requests
147144

148145
OptionsModel *optionsModel;

0 commit comments

Comments
 (0)