Details
-
Bug
-
Resolution: Done
-
P2: Important
-
5.15.2
-
None
-
-
1a8b7eb1d4f27e74621ee94c01dbeda3afd302c7 (qt/qtbase/dev) c0d71c8e051e9b13dbebb81ca2e91b1864ec8d34 (qt/tqtc-qtbase/5.15) 7eb6f9a04457feb27d6ba6685e38aa24a1600789 (qt/qtbase/6.2)
Description
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; }