- 
    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 |