Skip to content

Commit de7e92b

Browse files
jknockelbk138
authored andcommitted
libvncclient: fix tight decoding endianness issues
When the host byte order of a client is different from that of the RFB pixel format it is using, we must swap bytes before delivering them to the client. This commit addresses places where we were not properly doing that during tight decoding, manifesting in issues in which solid filled rectangles and gradients could be decoded to the wrong color. As the RFB protocol says: "Swap the pixel value according to big-endian-flag (e.g. if big-endian-flag is zero (false) and host byte order is big endian, then swap)."
1 parent 784cccb commit de7e92b

1 file changed

Lines changed: 54 additions & 16 deletions

File tree

src/libvncclient/tight.c

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,62 @@
5454

5555
#ifndef RGB_TO_PIXEL
5656

57-
#define RGB_TO_PIXEL(bpp,r,g,b) \
58-
(((CARD##bpp)(r) & client->format.redMax) << client->format.redShift | \
59-
((CARD##bpp)(g) & client->format.greenMax) << client->format.greenShift | \
60-
((CARD##bpp)(b) & client->format.blueMax) << client->format.blueShift)
61-
62-
#define RGB24_TO_PIXEL(bpp,r,g,b) \
63-
((((CARD##bpp)(r) & 0xFF) * client->format.redMax + 127) / 255 \
64-
<< client->format.redShift | \
65-
(((CARD##bpp)(g) & 0xFF) * client->format.greenMax + 127) / 255 \
66-
<< client->format.greenShift | \
67-
(((CARD##bpp)(b) & 0xFF) * client->format.blueMax + 127) / 255 \
68-
<< client->format.blueShift)
69-
70-
#define RGB24_TO_PIXEL32(r,g,b) \
71-
(((uint32_t)(r) & 0xFF) << client->format.redShift | \
72-
((uint32_t)(g) & 0xFF) << client->format.greenShift | \
57+
/*
58+
* Unfortunately we cannot use rfbClientSwap16IfLE() and related macros here as
59+
* rfbClientSwap16IfLE() swaps when the host byte order of the client is
60+
* little-endian, but we want to swap when the host byte order of the client is
61+
* different from the byte order of the pixel format it is using. In other
62+
* words, rfbClientSwap16IfLE() will do the right thing only when the pixel
63+
* format is big-endian.
64+
*/
65+
#define Swap8(c) (c)
66+
#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
67+
#define Swap32(l) ((((l) >> 24) & 0x000000ff)| \
68+
(((l) & 0x00ff0000) >> 8) | \
69+
(((l) & 0x0000ff00) << 8) | \
70+
(((l) & 0x000000ff) << 24))
71+
72+
#ifdef LIBVNCSERVER_WORDS_BIGENDIAN
73+
#define NEED_SWAP (!client->format.bigEndian)
74+
#else
75+
#define NEED_SWAP (client->format.bigEndian)
76+
#endif
77+
78+
#define RGB_TO_PIXEL_NOSWAP(card,r,g,b) \
79+
(((card)(r) & client->format.redMax) << client->format.redShift | \
80+
((card)(g) & client->format.greenMax) << client->format.greenShift | \
81+
((card)(b) & client->format.blueMax) << client->format.blueShift)
82+
83+
#define RGB_TO_PIXEL(bpp,r,g,b) NEED_SWAP ? \
84+
CONCAT2(Swap,bpp)(RGB_TO_PIXEL_NOSWAP(CARD##bpp,r,g,b)) : \
85+
RGB_TO_PIXEL_NOSWAP(CARD##bpp,r,g,b)
86+
87+
#define RGB24_TO_PIXEL_NOSWAP(card,r,g,b) \
88+
((((card)(r) & 0xFF) * client->format.redMax + 127) / 255 \
89+
<< client->format.redShift | \
90+
(((card)(g) & 0xFF) * client->format.greenMax + 127) / 255 \
91+
<< client->format.greenShift | \
92+
(((card)(b) & 0xFF) * client->format.blueMax + 127) / 255 \
93+
<< client->format.blueShift)
94+
95+
#define RGB24_TO_PIXEL(bpp,r,g,b) NEED_SWAP ? \
96+
CONCAT2(Swap,bpp)(RGB24_TO_PIXEL_NOSWAP(CARD##bpp,r,g,b)) : \
97+
RGB24_TO_PIXEL_NOSWAP(CARD##bpp,r,g,b)
98+
99+
#define RGB24_TO_PIXEL32_NOSWAP(r,g,b) \
100+
(((uint32_t)(r) & 0xFF) << client->format.redShift | \
101+
((uint32_t)(g) & 0xFF) << client->format.greenShift | \
73102
((uint32_t)(b) & 0xFF) << client->format.blueShift)
74103

104+
#define RGB24_TO_PIXEL32_SWAP(r,g,b) \
105+
(((uint32_t)(r) & 0xFF) << (24 - client->format.redShift) | \
106+
((uint32_t)(g) & 0xFF) << (24 - client->format.greenShift) | \
107+
((uint32_t)(b) & 0xFF) << (24 - client->format.blueShift))
108+
109+
#define RGB24_TO_PIXEL32(r,g,b) NEED_SWAP ? \
110+
RGB24_TO_PIXEL32_SWAP(r,g,b) : \
111+
RGB24_TO_PIXEL32_NOSWAP(r,g,b)
112+
75113
#endif
76114

77115
/* Type declarations */

0 commit comments

Comments
 (0)