fix: handle top-down DIB images in clipboard bitmap converter
A BITMAPINFOHEADER with negative biHeight (top-down DIB) caused std::length_error crash in toIClipboard because 4 * w * h went negative and wrapped to a huge size_t in string::append. Fix: use abs(height) for buffer size and SetDIBitsToDevice, and add null check for CreateDIBSection. fixes: #9869
This commit is contained in:
parent
3c37f2ff11
commit
40f743fb37
1 changed files with 10 additions and 2 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Deskflow -- mouse and keyboard sharing utility
|
* Deskflow -- mouse and keyboard sharing utility
|
||||||
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
* SPDX-FileCopyrightText: (C) 2012 - 2016 Synergy App Ltd
|
||||||
|
* SPDX-FileCopyrightText: (C) 2026 Deskflow Developers
|
||||||
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
* SPDX-FileCopyrightText: (C) 2004 Chris Schoeneman
|
||||||
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
* SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,6 +73,7 @@ std::string MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
|
||||||
BITMAPINFOHEADER info;
|
BITMAPINFOHEADER info;
|
||||||
LONG w = bitmap->bmiHeader.biWidth;
|
LONG w = bitmap->bmiHeader.biWidth;
|
||||||
LONG h = bitmap->bmiHeader.biHeight;
|
LONG h = bitmap->bmiHeader.biHeight;
|
||||||
|
const LONG absHeight = (h < 0) ? -h : h;
|
||||||
info.biSize = sizeof(BITMAPINFOHEADER);
|
info.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
info.biWidth = w;
|
info.biWidth = w;
|
||||||
info.biHeight = h;
|
info.biHeight = h;
|
||||||
|
|
@ -85,6 +87,12 @@ std::string MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
|
||||||
info.biClrImportant = 0;
|
info.biClrImportant = 0;
|
||||||
HDC dc = GetDC(nullptr);
|
HDC dc = GetDC(nullptr);
|
||||||
HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO *)&info, DIB_RGB_COLORS, &raw, nullptr, 0);
|
HBITMAP dst = CreateDIBSection(dc, (BITMAPINFO *)&info, DIB_RGB_COLORS, &raw, nullptr, 0);
|
||||||
|
if (dst == nullptr || raw == nullptr) {
|
||||||
|
LOG_WARN("failed to allocate destination bitmap for clipboard image");
|
||||||
|
ReleaseDC(nullptr, dc);
|
||||||
|
GlobalUnlock(data);
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
// find the start of the pixel data
|
// find the start of the pixel data
|
||||||
const char *srcBits = (const char *)bitmap + bitmap->bmiHeader.biSize;
|
const char *srcBits = (const char *)bitmap + bitmap->bmiHeader.biSize;
|
||||||
|
|
@ -103,14 +111,14 @@ std::string MSWindowsClipboardBitmapConverter::toIClipboard(HANDLE data) const
|
||||||
// copy source image to destination image
|
// copy source image to destination image
|
||||||
HDC dstDC = CreateCompatibleDC(dc);
|
HDC dstDC = CreateCompatibleDC(dc);
|
||||||
HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
|
HGDIOBJ oldBitmap = SelectObject(dstDC, dst);
|
||||||
SetDIBitsToDevice(dstDC, 0, 0, w, h, 0, 0, 0, h, srcBits, bitmap, DIB_RGB_COLORS);
|
SetDIBitsToDevice(dstDC, 0, 0, w, absHeight, 0, 0, 0, absHeight, srcBits, bitmap, DIB_RGB_COLORS);
|
||||||
SelectObject(dstDC, oldBitmap);
|
SelectObject(dstDC, oldBitmap);
|
||||||
DeleteDC(dstDC);
|
DeleteDC(dstDC);
|
||||||
GdiFlush();
|
GdiFlush();
|
||||||
|
|
||||||
// extract data
|
// extract data
|
||||||
std::string image((const char *)&info, info.biSize);
|
std::string image((const char *)&info, info.biSize);
|
||||||
image.append((const char *)raw, 4 * w * h);
|
image.append((const char *)raw, static_cast<size_t>(4) * static_cast<size_t>(w) * static_cast<size_t>(absHeight));
|
||||||
|
|
||||||
// clean up GDI
|
// clean up GDI
|
||||||
DeleteObject(dst);
|
DeleteObject(dst);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue