Forum Discussion

Chlumsky's avatar
Chlumsky
Copper Contributor
Nov 03, 2025

Serious bug in Windows clipboard - images get corrupted!

Windows supports two formats of image data in the clipboard: CF_DIB and CF_DIBV5. They are (supposed to be) intercompatible - a program can store a bitmap in one of the formats and load it in the other, while Windows takes care of the conversion. However, the conversion from CF_DIB to CF_DIBV5 performed by Windows 11 is incorrect! I've tested this in versions 23H2, 24H2, and 25H2, the bug is present in all of them (and possibly in earlier versions too).

There is a very simple way reproduce it:

  1. Take a screenshot into the clipboard (Alt + Print Screen)
  2. Run the following C/C++ program:
#include <Windows.h>

int main(void) {
    if (!OpenClipboard(NULL))
        return -1;
    GetClipboardData(CF_DIBV5);
    CloseClipboard();
    return 0;
}

This will force the CF_DIB to CF_DIBV5 conversion.

3. Open MS Paint and paste the screenshot.

You will get a corrupted image:

It might be a bit hard to see here, but essentially, the entire pixel array is shifted by 3 pixels. In the bottom left corner, you can see 3 superfluous pixels (red, green, and blue, so the actual image begins at the 4th pixel in the bottom row and the rightmost 3 columns appear on the left side shifted up by 1 row.

Here is another example of a correct image (left) and corrupted image (right) where the column transposition is more apparent.

Even if we assume that both my and MS Paint's interpretation of the CF_DIBV5 format is incorrect, we can do the following sequence of operations:

  1. Store image into clipboard as CF_DIB
  2. Load image from clipboard as CF_DIBV5 (forcing Windows to perform the conversion) and store the bitmap data
  3. Empty the clipboard
  4. Store the previously retrieved bitmap data unchanged back into the clipboard as CF_DIBV5
  5. Load image from clipboard as CF_DIB, forcing the opposite conversion

The resulting image will not be the same as the one initially put in, but will be corrupted in the same way as I demonstrated above. This proves that the error is in Windows's handling of clipboard DIB data conversion.

This specifically happens for the format Windows uses for screenshots - BI_BITFIELDS and 32 bits per pixel. The conversion appears to correctly convert the DIB header, but then just takes the remainder of the data and copies them. The problem is that in BI_BITFIELDS mode, the V1 header requires additional 12 bytes of the bitfield masks to be placed between the header and the pixel data, while for DIB V5, these 12 bytes are included in the (larger) header. So what happens is that instead of the 12 mask bytes being absorbed into the header, they are kept after it, in the part that is strictly for pixel data in V5 (these are the three RGB pixels), shifting the entire pixel array back by 12 bytes.

 

Resources