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 Change-Id: I45818ada6d884b06028056d28635390a300e2def Reviewed-by: Andy Shaw <andy.shaw@qt.io> (cherry picked from commit c42ebd5ba6f1fb861cabdbe44ab10df55b9b3ada) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
874cc1e9f6
commit
68ba065602
@ -1,6 +1,6 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of the QtSql module of the Qt Toolkit.
|
** This file is part of the QtSql module of the Qt Toolkit.
|
||||||
@ -226,6 +226,7 @@ public:
|
|||||||
OCISvcCtx *svc;
|
OCISvcCtx *svc;
|
||||||
OCIServer *srvhp;
|
OCIServer *srvhp;
|
||||||
OCISession *authp;
|
OCISession *authp;
|
||||||
|
OCITrans *trans = nullptr;
|
||||||
OCIError *err;
|
OCIError *err;
|
||||||
bool transaction;
|
bool transaction;
|
||||||
int serverVersion;
|
int serverVersion;
|
||||||
@ -2296,11 +2297,12 @@ bool QOCIDriver::open(const QString & db,
|
|||||||
r = OCIAttrSet(d->authp, OCI_HTYPE_SESSION, const_cast<ushort *>(password.utf16()),
|
r = OCIAttrSet(d->authp, OCI_HTYPE_SESSION, const_cast<ushort *>(password.utf16()),
|
||||||
password.length() * sizeof(QChar), OCI_ATTR_PASSWORD, d->err);
|
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)
|
if (r == OCI_SUCCESS)
|
||||||
r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&trans), OCI_HTYPE_TRANS, 0, 0);
|
r = OCIAttrSet(d->svc, OCI_HTYPE_SVCCTX, d->trans, 0, OCI_ATTR_TRANS, d->err);
|
||||||
if (r == OCI_SUCCESS)
|
|
||||||
r = OCIAttrSet(d->svc, OCI_HTYPE_SVCCTX, trans, 0, OCI_ATTR_TRANS, d->err);
|
|
||||||
|
|
||||||
if (r == OCI_SUCCESS) {
|
if (r == OCI_SUCCESS) {
|
||||||
if (user.isEmpty() && password.isEmpty())
|
if (user.isEmpty() && password.isEmpty())
|
||||||
@ -2314,12 +2316,18 @@ bool QOCIDriver::open(const QString & db,
|
|||||||
if (r != OCI_SUCCESS) {
|
if (r != OCI_SUCCESS) {
|
||||||
setLastError(qMakeError(tr("Unable to logon"), QSqlError::ConnectionError, d->err));
|
setLastError(qMakeError(tr("Unable to logon"), QSqlError::ConnectionError, d->err));
|
||||||
setOpenError(true);
|
setOpenError(true);
|
||||||
|
if (d->trans)
|
||||||
|
OCIHandleFree(d->trans, OCI_HTYPE_TRANS);
|
||||||
|
d->trans = nullptr;
|
||||||
if (d->authp)
|
if (d->authp)
|
||||||
OCIHandleFree(d->authp, OCI_HTYPE_SESSION);
|
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)
|
if (d->srvhp)
|
||||||
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
|
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
|
||||||
d->srvhp = 0;
|
d->srvhp = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2359,12 +2367,14 @@ void QOCIDriver::close()
|
|||||||
|
|
||||||
OCISessionEnd(d->svc, d->err, d->authp, OCI_DEFAULT);
|
OCISessionEnd(d->svc, d->err, d->authp, OCI_DEFAULT);
|
||||||
OCIServerDetach(d->srvhp, d->err, OCI_DEFAULT);
|
OCIServerDetach(d->srvhp, d->err, OCI_DEFAULT);
|
||||||
|
OCIHandleFree(d->trans, OCI_HTYPE_TRANS);
|
||||||
|
d->trans = nullptr;
|
||||||
OCIHandleFree(d->authp, OCI_HTYPE_SESSION);
|
OCIHandleFree(d->authp, OCI_HTYPE_SESSION);
|
||||||
d->authp = 0;
|
d->authp = nullptr;
|
||||||
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
|
|
||||||
d->srvhp = 0;
|
|
||||||
OCIHandleFree(d->svc, OCI_HTYPE_SVCCTX);
|
OCIHandleFree(d->svc, OCI_HTYPE_SVCCTX);
|
||||||
d->svc = 0;
|
d->svc = nullptr;
|
||||||
|
OCIHandleFree(d->srvhp, OCI_HTYPE_SERVER);
|
||||||
|
d->srvhp = nullptr;
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
setOpenError(false);
|
setOpenError(false);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user