Skip to content

fix: handle BMP V4/V5 headers in cross-platform clipboard image transfer#1

Open
hsddszjs wants to merge 7 commits into
masterfrom
claude/fix-cross-platform-clipboard-bPT5u
Open

fix: handle BMP V4/V5 headers in cross-platform clipboard image transfer#1
hsddszjs wants to merge 7 commits into
masterfrom
claude/fix-cross-platform-clipboard-bPT5u

Conversation

@hsddszjs
Copy link
Copy Markdown
Owner

@hsddszjs hsddszjs commented Apr 5, 2026

Summary

  • Fix macOS-to-Windows clipboard image transfer producing a white/blank image
  • macOS generates BMP with BITMAPV4HEADER (108 bytes) or BITMAPV5HEADER (124 bytes) for screenshots, but the converter hardcoded the header size to 40 bytes, truncating it and corrupting the image
  • Fix toIClipboard: strip only the 14-byte BMP file header, keeping the entire DIB intact
  • Fix fromIClipboard: compute pixel offset from actual DIB header metadata instead of hardcoding 54
  • Applied the same fix to both OSX and XWindows clipboard converters

Test plan

  • Copy screenshot on macOS, paste on Windows — should show correct image (not white)
  • Copy screenshot on Windows, paste on macOS — should still work as before
  • Copy screenshot on Linux, paste on Windows/macOS — should work correctly

https://claude.ai/code/session_015Y82naHd7Tuj1inyFJtKmP

claude and others added 7 commits April 5, 2026 09:58
macOS generates BMP data with BITMAPV4HEADER (108 bytes) or
BITMAPV5HEADER (124 bytes) for screenshots, but the BMP-to-DIB
conversion hardcoded the header size to 40 bytes
(BITMAPINFOHEADER). This truncated the header while biSize still
indicated 108/124 bytes, causing Windows to read pixel data as
header data and display a white/corrupt image.

Fix toIClipboard: strip only the 14-byte BMP file header, keeping
the entire DIB intact (header + color table + pixel data).

Fix fromIClipboard: compute the BMP file pixel offset from the
actual DIB header size and color table, instead of hardcoding 54.

Applied the same fix to both OSX and XWindows clipboard converters.

https://claude.ai/code/session_015Y82naHd7Tuj1inyFJtKmP
When Windows re-reads CF_DIB data with a BITMAPV4HEADER (108 bytes)
or BITMAPV5HEADER (124 bytes), the pixel data pointer was calculated
incorrectly. The code unconditionally added 3 DWORDs (12 bytes) for
BI_BITFIELDS color masks after the header, but V4/V5 headers include
these masks within the header itself. This caused srcBits to point
12 bytes past the actual pixel data start, potentially reading past
the allocated buffer and crashing the server — which disconnected
the macOS client.

Fix: only add the extra color mask offset for BITMAPINFOHEADER
(biSize == 40), since V4/V5 headers already contain the masks.

https://claude.ai/code/session_015Y82naHd7Tuj1inyFJtKmP
When files are copied on macOS (e.g., in Finder), the pasteboard
contains file reference data but no native image types. However,
macOS's UTI auto-conversion may claim com.microsoft.bmp is available
and attempt to convert file references to BMP format. This conversion
can hang indefinitely, blocking the client's event loop and causing
a keep-alive timeout disconnect from the server.

Fix: before checking for bitmap clipboard data, verify that the
pasteboard actually contains native image data (public.tiff or
public.png). Skip bitmap processing entirely when only file
references are present.

https://claude.ai/code/session_015Y82naHd7Tuj1inyFJtKmP
Fixes across all platforms for issues that can occur during regular
clipboard operations:

Windows:
- Fix out-of-bounds read in convertLinefeedToUnix when text ends
  with \r without following \n (check n > 1 before accessing scan[1])
- Fix missing GlobalUnlock when srcSize <= 1 in text converter
- Add null checks for GetDC, CreateDIBSection, CreateCompatibleDC
  in bitmap converter to prevent crash under GDI resource pressure
- Add integer overflow protection for large bitmap dimensions
  (4 * w * h) using 64-bit arithmetic and reasonable size limits
- Validate biBitCount range before bit shift in color table calc
- Add bounds check for HTML fragment start/end offsets

macOS / XWindows:
- Validate biSize range (40-1024) in BMP fromIClipboard to prevent
  reading past buffer with unusual header sizes
- Ensure buffer is large enough before reading DIB header fields
- Fix CFStringGetBytes buffSize <= 0 not checked before allocation
  in text and HTML converters (was checking new return instead)

Common:
- Add bounds checking in IClipboard::unmarshall to prevent reading
  past buffer end with truncated/corrupt network data
- Fix ClipboardChunk::assemble toULong parse error not checked
- Fix LOG_ERR format specifier: use %zu for size_t values
- Fix StreamChunker infinite loop when size == 0

https://claude.ai/code/session_015Y82naHd7Tuj1inyFJtKmP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants