Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-84613

Crash in QWindowsXPStylePrivate::fixAlphaChannel with HDPI

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Not Evaluated
    • Resolution: Done
    • Affects Version/s: 5.15.0
    • Fix Version/s: 5.15.1
    • Component/s: GUI: High-DPI
    • Labels:
      None
    • Platform/s:
      Windows
    • Commits:
      13d95e415e0870fd13ebef8b888364d8b9ebb9e5 (qt/qtbase/dev) c988a2b25b3d76a5ba50b86963a53704f43ad1b5 (qt/qtbase/5.15)

      Description

      I have a crash, memory exception, on a news HP portable Spectre x360, with high resolutions screen.

      Using QT 5.15.0.
      With Qt 5.12 we do not have any problems.

      The problem should be related to introduction of the correctionFactor for HDPI. 
      The function fixAlphaChannel function is called with a QRect that is larger than the drawRect that is used to create the buffer. 

      In the function QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer 2 rectangles are created.
      The drawRect is smaller when there is a correctionFactor.
      On my computer the correctionFactor is 2.

      const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1));
      {{ QRect rect = rectF.toRect();}}
      {{ QRect drawRect = hasCorrectionFactor}}
      {{ ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect() : rect;}}

      For the creation of the buffer it is used the drawRect that is the one that is smaller.

      if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size
      return false;

      HBITMAP QWindowsXPStylePrivate::buffer(int w, int h)
      {{ {}}
      {{ // If we already have a HBITMAP which is of adequate size, just return that}}
      {{ if (bufferBitmap)}}{{

      { if (bufferW >= w && bufferH >= h) return bufferBitmap; // Not big enough, discard the old one if (bufferDC && nullBitmap) SelectObject(bufferDC, nullBitmap); DeleteObject(bufferBitmap); bufferBitmap = nullptr; }

      }}w = qMax(bufferW, w);
      {{ h = qMax(bufferH, h);}}if (!bufferDC){{

      { HDC displayDC = GetDC(nullptr); bufferDC = CreateCompatibleDC(displayDC); ReleaseDC(nullptr, displayDC); }

      }}// Define the header
      {{ BITMAPINFO bmi;}}
      {{ memset(&bmi, 0, sizeof(bmi));}}
      {{ bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);}}
      {{ bmi.bmiHeader.biWidth = w;}}
      {{ bmi.bmiHeader.biHeight = -h;}}
      {{ bmi.bmiHeader.biPlanes = 1;}}
      {{ bmi.bmiHeader.biBitCount = 32;}}
      {{ bmi.bmiHeader.biCompression = BI_RGB;}}// Create the pixmap
      {{ bufferPixels = nullptr;}}
      {{ bufferBitmap = CreateDIBSection(bufferDC, &bmi, DIB_RGB_COLORS, reinterpret_cast<void *>(&*bufferPixels), nullptr, 0);}}
      {{ GdiFlush();}}

      Instead the fixAlpaChannel is called with the larger rect size.

      // Fix alpha values, if needed
      {{ if (potentialInvalidAlpha)}}
      {{ wasAlphaFixed = fixAlphaChannel(rect);}}

      The crash is when using the buffer at a position that is apparantly larger than the one used for creation.

      {{bool QWindowsXPStylePrivate::fixAlphaChannel(const QRect &rect)}}
      {{ }
      {{ const int startX = rect.left();}}
      {{ {{ const int startY = rect.top();}}}}
      {{ {{ const int w = rect.width();}}}}
      {{ {{ const int h = rect.height();}}}}
      {{ {{ bool hasFixedAlphaValue = false;}}for (int y = startY; y < h; ++y) {}}
      {{ {{ auto buffer = reinterpret_cast<DWORD >(*bufferPixels) + (y * bufferW);}}}}
      {{ {{ for (int x = startX; x < w; ++x, ++buffer) {}}}}
      {{ {{ uint pixel = *buffer; // crash here}}}}
      {{ {{ int alpha = qAlpha(pixel);}}}}
      {{ {{ if (qRed(pixel) > alpha || qGreen(pixel) > alpha || qBlue(pixel) > alpha) {}}}}
      {{ {{ *buffer |= 0xff000000;}}}}
      {{ {{ hasFixedAlphaValue = true;}}}}
      {{ {{ }}}}}
      {{ {{ }}}}}
      {{ {{ }}}}}
      {{ {{ return hasFixedAlphaValue;}}}}
      {{ }}}

      On a normal video, with the correctionFactor = 1 there are no problems.

      I did not check what exactly this function is doing. But I did noticed that the crash does not happen always even if the size are not the same. Probably on many computers the situation goes unoticed.

      Let me know if you need more informtion.

       

       

       

        Attachments

          Issue Links

          No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            Activity

              People

              Assignee:
              kleint Friedemann Kleint
              Reporter:
              domezuk Domenico Zucchetti
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Gerrit Reviews

                  There are no open Gerrit changes