Fix leak of transaction context handle in QSql's OCI driver

Transaction handles were allocated but nowhere freed. Thanks to Stefan
Latsch for pointing this out and suggesting the fix. Make the handle
yet another member of QOCIDriverPrivate so that close() can free
it. At the same time, also free the service context handle d->svc when
failing do open(); and shuffle the order of frees to be the reverse of
the order of allocations.

Fixes: QTBUG-94246
Pick-to: 6.2 6.1 5.15
Change-Id: I45818ada6d884b06028056d28635390a300e2def
Reviewed-by: Andy Shaw <andy.shaw@qt.io>
This commit is contained in:
Edward Welbourne 2021-06-21 12:03:10 +02:00
parent d201c90c1c
commit c42ebd5ba6

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtSql module of the Qt Toolkit.
@ -226,6 +226,7 @@ public:
OCISvcCtx *svc;
OCIServer *srvhp;
OCISession *authp;
OCITrans *trans = nullptr;
OCIError *err;
bool transaction;
int serverVersion;
@ -2296,11 +2297,12 @@ bool QOCIDriver::open(const QString & db,
r = OCIAttrSet(d->authp, OCI_HTYPE_SESSION, const_cast<ushort *>(password.utf16()),
password.length() * sizeof(QChar), OCI_ATTR_PASSWORD, d->err);
OCITrans* trans;
if (r == OCI_SUCCESS) {
r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&d->trans), OCI_HTYPE_TRANS,
0, nullptr);
}
if (r == OCI_SUCCESS)
r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&trans), OCI_HTYPE_TRANS, 0, 0);
if (r == OCI_SUCCESS)
r = OCIAttrSet(d->svc, OCI_HTYPE_SVCCTX, trans, 0, OCI_ATTR_TRANS, d->err);
r = OCIAttrSet(d->svc, OCI_HTYPE_SVCCTX, d->trans, 0, OCI_ATTR_TRANS, d->err);
if (r == OCI_SUCCESS) {
if (user.isEmpty() && password.isEmpty())
@ -2314,12 +2316,18 @@ bool QOCIDriver::open(const QString & db,
if (r != OCI_SUCCESS) {
setLastError(qMakeError(tr("Unable to logon"), QSqlError::ConnectionError, d->err));
setOpenError(true);
if (d->trans)
OCIHandleFree(d->trans, OCI_HTYPE_TRANS);
d->trans = nullptr;
if (d->authp)
OCIHandleFree(d->authp, OCI_HTYPE_SESSION);
d->authp = 0;
d->authp = nullptr;
if (d->svc)
OCIHandleFree(d->svc, OCI_HTYPE_SVCCTX);
d->svc = nullptr;
if (d->srvhp)
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
d->srvhp = 0;
d->srvhp = nullptr;
return false;
}
@ -2359,12 +2367,14 @@ void QOCIDriver::close()
OCISessionEnd(d->svc, d->err, d->authp, OCI_DEFAULT);
OCIServerDetach(d->srvhp, d->err, OCI_DEFAULT);
OCIHandleFree(d->trans, OCI_HTYPE_TRANS);
d->trans = nullptr;
OCIHandleFree(d->authp, OCI_HTYPE_SESSION);
d->authp = 0;
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
d->srvhp = 0;
d->authp = nullptr;
OCIHandleFree(d->svc, OCI_HTYPE_SVCCTX);
d->svc = 0;
d->svc = nullptr;
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
d->srvhp = nullptr;
setOpen(false);
setOpenError(false);
}