-
Bug
-
Resolution: Done
-
P2: Important
-
5.15.2
-
None
-
-
1a8b7eb1d4f27e74621ee94c01dbeda3afd302c7 (qt/qtbase/dev) c0d71c8e051e9b13dbebb81ca2e91b1864ec8d34 (qt/tqtc-qtbase/5.15) 7eb6f9a04457feb27d6ba6685e38aa24a1600789 (qt/qtbase/6.2)
QImage::reinterpretAsFormat causes an incorrect reference count if it fails due to lack of memory.
The following code can be used to reproduce the problem:
poPreparedImage = new QImage(oQImage); if (!poPreparedImage->reinterpretAsFormat(QImage::Format::Format_ARGB32_Premultiplied)) { // Error due to low memory delete poPreparedImage; // After this the data pointer in oQImage is deleted and the object is corrupt }
The problem ist that the call of copy() in detach() in reinterpretAsFormat() decrements the reference count by one. The d objects are swapped and the original is decremeted in the line with the copy.
Extract of the erroneous Qt code:
void QImage::detach()
{
if (d) {
if (d->is_cached && d->ref.loadRelaxed() == 1)
QImagePixmapCleanupHooks::executeImageHooks(cacheKey()); if (d->ref.loadRelaxed() != 1 || d->ro_data)
*this = copy(); if (d)
++d->detach_no;
}
}
bool QImage::reinterpretAsFormat(Format format)
{
if (!d)
return false;
if (d->format == format)
return true;
if (qt_depthForFormat(format) != qt_depthForFormat(d->format))
return false;
if (!isDetached()) { // Detach only if shared, not for read-only data.
QImageData *oldD = d;
detach();
// In case detach() ran out of memory
if (!d) {
d = oldD;
return false;
}
} d->format = format;
return true;
}
| For Gerrit Dashboard: QTBUG-98377 | ||||||
|---|---|---|---|---|---|---|
| # | Subject | Branch | Project | Status | CR | V |
| 381597,3 | Increment reference count when restoring reference | dev | qt/qtbase | Status: MERGED | +2 | 0 |
| 381981,2 | Increment reference count when restoring reference | 6.2 | qt/qtbase | Status: MERGED | +2 | 0 |
| 381982,2 | Increment reference count when restoring reference | tqtc/lts-5.15 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |