Skip to content

Commit 0640ba5

Browse files
gujjwal00bk138
authored andcommitted
libvncclient: Improve Extended Clipboard encoding compatibility
Many servers can't handle zlib streams created by compress() function of zlib library. Primary bug is that these servers don't expect inflate() to return Z_STREAM_END, which is the case for streams created by compress(). Affected servers: LibVNCServer UltraVNC TigerVNC (<= 1.10)
1 parent 81609f0 commit 0640ba5

1 file changed

Lines changed: 38 additions & 1 deletion

File tree

src/libvncclient/rfbclient.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,6 +1801,43 @@ sendExtClientCutTextNotify(rfbClient *client)
18011801
return ret;
18021802
}
18031803

1804+
/**
1805+
* Due to bugs, many servers (including most versions of LibVNCServer) can't
1806+
* properly handle zlib streams created by compress() function of zlib library.
1807+
*
1808+
* Primary bug is that these servers don't expect inflate() to return Z_STREAM_END
1809+
* which is the case for (correct) streams created by compress().
1810+
*
1811+
* So this function creates a compatible stream, for which inflate() returns Z_OK.
1812+
* This is how some clients create zlib streams, unintentionally avoiding the bug.
1813+
*/
1814+
static int
1815+
CompressClipData(Bytef *dest, uLongf *destLen, Bytef *source, uLong sourceLen)
1816+
{
1817+
int ret;
1818+
z_stream *zs = (z_stream*)malloc(sizeof(z_stream));
1819+
memset(zs, 0, sizeof(z_stream));
1820+
1821+
zs->zfree = Z_NULL;
1822+
zs->zalloc = Z_NULL;
1823+
zs->opaque = Z_NULL;
1824+
ret = deflateInit(zs, Z_DEFAULT_COMPRESSION);
1825+
if (ret == Z_OK) {
1826+
zs->avail_in = sourceLen;
1827+
zs->next_in = source;
1828+
zs->avail_out = *destLen;
1829+
zs->next_out = dest;
1830+
1831+
do {
1832+
// Using Z_SYNC_FLUSH instead of Z_FINISH is the key here.
1833+
ret = deflate(zs, Z_SYNC_FLUSH);
1834+
} while (ret >= 0 && zs->avail_in > 0);
1835+
1836+
*destLen = zs->total_out;
1837+
deflateEnd(zs);
1838+
}
1839+
return ret;
1840+
}
18041841

18051842
/*
18061843
* sendExtClientCutTextProvide
@@ -1834,7 +1871,7 @@ sendExtClientCutTextProvide(rfbClient *client, char* data, int len)
18341871
return FALSE;
18351872
}
18361873
memcpy(cbuf, &be_flags, sizeof(be_flags));
1837-
if (compress(cbuf + sizeof(be_flags), &csz, buf, sz_to_compressed) != Z_OK) {
1874+
if (CompressClipData(cbuf + sizeof(be_flags), &csz, buf, sz_to_compressed) != Z_OK) {
18381875
rfbClientLog("sendExtClientCutTextProvide: compress cbuf failed\n");
18391876
free(buf);
18401877
free(cbuf);

0 commit comments

Comments
 (0)