diff --git a/SOURCES/tigervnc-1.3.1-do-not-die-when-port-is-already-taken.patch b/SOURCES/tigervnc-1.3.1-do-not-die-when-port-is-already-taken.patch deleted file mode 100644 index 3623b14..0000000 --- a/SOURCES/tigervnc-1.3.1-do-not-die-when-port-is-already-taken.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/unix/vncserver b/unix/vncserver -index a6c890f..687ef72 100755 ---- a/unix/vncserver -+++ b/unix/vncserver -@@ -208,7 +208,8 @@ if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { - $displayNumber = $1; - shift(@ARGV); - if (!&CheckDisplayNumber($displayNumber)) { -- die "A VNC server is already running as :$displayNumber\n"; -+ warn "A VNC server is already running as :$displayNumber\n"; -+ $displayNumber = &GetDisplayNumber(); - } - } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) { - &Usage(); diff --git a/SOURCES/tigervnc-CVE-2019-15691.patch b/SOURCES/tigervnc-CVE-2019-15691.patch new file mode 100644 index 0000000..1b0a6c8 --- /dev/null +++ b/SOURCES/tigervnc-CVE-2019-15691.patch @@ -0,0 +1,116 @@ +From d61a767d6842b530ffb532ddd5a3d233119aad40 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 10 Sep 2019 11:05:48 +0200 +Subject: [PATCH] Make ZlibInStream more robust against failures + +Move the checks around to avoid missing cases where we might access +memory that is no longer valid. Also avoid touching the underlying +stream implicitly (e.g. via the destructor) as it might also no +longer be valid. + +A malicious server could theoretically use this for remote code +execution in the client. + +Issue found by Pavel Cheremushkin from Kaspersky Lab +--- + common/rdr/ZlibInStream.cxx | 13 +++++++------ + common/rdr/ZlibInStream.h | 2 +- + common/rfb/CMsgReader.cxx | 3 ++- + common/rfb/SMsgReader.cxx | 3 ++- + common/rfb/TightDecoder.cxx | 3 ++- + common/rfb/zrleDecode.h | 3 ++- + 6 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/common/rdr/ZlibInStream.cxx b/common/rdr/ZlibInStream.cxx +index 4053bd1..a361010 100644 +--- a/common/rdr/ZlibInStream.cxx ++++ b/common/rdr/ZlibInStream.cxx +@@ -52,16 +52,16 @@ int ZlibInStream::pos() + return offset + ptr - start; + } + +-void ZlibInStream::removeUnderlying() ++void ZlibInStream::flushUnderlying() + { + ptr = end = start; +- if (!underlying) return; + + while (bytesIn > 0) { + decompress(true); + end = start; // throw away any data + } +- underlying = 0; ++ ++ setUnderlying(NULL, 0); + } + + void ZlibInStream::reset() +@@ -90,7 +90,7 @@ void ZlibInStream::init() + void ZlibInStream::deinit() + { + assert(zs != NULL); +- removeUnderlying(); ++ setUnderlying(NULL, 0); + inflateEnd(zs); + delete zs; + zs = NULL; +@@ -100,8 +100,6 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait) + { + if (itemSize > bufSize) + throw Exception("ZlibInStream overrun: max itemSize exceeded"); +- if (!underlying) +- throw Exception("ZlibInStream overrun: no underlying stream"); + + if (end - ptr != 0) + memmove(start, ptr, end - ptr); +@@ -127,6 +125,9 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait) + + bool ZlibInStream::decompress(bool wait) + { ++ if (!underlying) ++ throw Exception("ZlibInStream overrun: no underlying stream"); ++ + zs->next_out = (U8*)end; + zs->avail_out = start + bufSize - end; + +diff --git a/common/rdr/ZlibInStream.h b/common/rdr/ZlibInStream.h +index 6bd4da4..86ba1ff 100644 +--- a/common/rdr/ZlibInStream.h ++++ b/common/rdr/ZlibInStream.h +@@ -38,7 +38,7 @@ namespace rdr { + virtual ~ZlibInStream(); + + void setUnderlying(InStream* is, int bytesIn); +- void removeUnderlying(); ++ void flushUnderlying(); + int pos(); + void reset(); + +diff --git a/common/rfb/TightDecoder.cxx b/common/rfb/TightDecoder.cxx +index 3a1254a..4273eb7 100644 +--- a/common/rfb/TightDecoder.cxx ++++ b/common/rfb/TightDecoder.cxx +@@ -340,7 +340,8 @@ void TightDecoder::decodeRect(const Rect& r, const void* buffer, + + zis[streamId].readBytes(netbuf, dataSize); + +- zis[streamId].removeUnderlying(); ++ zis[streamId].flushUnderlying(); ++ zis[streamId].setUnderlying(NULL, 0); + delete ms; + + bufptr = netbuf; +diff --git a/common/rfb/zrleDecode.h b/common/rfb/zrleDecode.h +index 0bfbbe1..a69ca67 100644 +--- a/common/rfb/zrleDecode.h ++++ b/common/rfb/zrleDecode.h +@@ -178,7 +178,8 @@ void ZRLE_DECODE (const Rect& r, rdr::InStream* is, + } + } + +- zis->removeUnderlying(); ++ zis->flushUnderlying(); ++ zis->setUnderlying(NULL, 0); + } + + #undef ZRLE_DECODE diff --git a/SOURCES/tigervnc-CVE-2019-15692.patch b/SOURCES/tigervnc-CVE-2019-15692.patch new file mode 100644 index 0000000..4b0e983 --- /dev/null +++ b/SOURCES/tigervnc-CVE-2019-15692.patch @@ -0,0 +1,71 @@ +From 996356b6c65ca165ee1ea46a571c32a1dc3c3821 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 10 Sep 2019 15:21:03 +0200 +Subject: [PATCH] Restrict PixelBuffer dimensions to safe values + +We do a lot of calculations based on pixel coordinates and we need +to make sure they do not overflow. Restrict the maximum dimensions +we support rather than try to switch over all calculations to use +64 bit integers. + +This prevents attackers from from injecting code by specifying a +huge framebuffer size and relying on the values overflowing to +access invalid areas of the heap. + +This primarily affects the client which gets both the screen +dimensions and the pixel contents from the remote side. But the +server might also be affected as a client can adjust the screen +dimensions, as can applications inside the session. + +Issue found by Pavel Cheremushkin from Kaspersky Lab. +--- + common/rfb/PixelBuffer.cxx | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx +index ad58324..18f41f8 100644 +--- a/common/rfb/PixelBuffer.cxx ++++ b/common/rfb/PixelBuffer.cxx +@@ -31,6 +31,14 @@ using namespace rdr; + + static LogWriter vlog("PixelBuffer"); + ++// We do a lot of byte offset calculations that assume the result fits ++// inside a signed 32 bit integer. Limit the maximum size of pixel ++// buffers so that these calculations never overflow. ++ ++const int maxPixelBufferWidth = 16384; ++const int maxPixelBufferHeight = 16384; ++const int maxPixelBufferStride = 16384; ++ + + // -=- Generic pixel buffer class + +@@ -108,6 +116,11 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf, + + void PixelBuffer::setSize(int width, int height) + { ++ if ((width < 0) || (width > maxPixelBufferWidth)) ++ throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width); ++ if ((height < 0) || (height > maxPixelBufferHeight)) ++ throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested", height); ++ + width_ = width; + height_ = height; + } +@@ -337,6 +350,15 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons + void FullFramePixelBuffer::setBuffer(int width, int height, + rdr::U8* data_, int stride_) + { ++ if ((width < 0) || (width > maxPixelBufferWidth)) ++ throw rfb::Exception("Invalid PixelBuffer width of %d pixels requested", width); ++ if ((height < 0) || (height > maxPixelBufferHeight)) ++ throw rfb::Exception("Invalid PixelBuffer height of %d pixels requested", height); ++ if ((stride_ < 0) || (stride_ > maxPixelBufferStride) || (stride_ < width)) ++ throw rfb::Exception("Invalid PixelBuffer stride of %d pixels requested", stride_); ++ if ((width != 0) && (height != 0) && (data_ == NULL)) ++ throw rfb::Exception("PixelBuffer requested without a valid memory area"); ++ + ModifiablePixelBuffer::setSize(width, height); + stride = stride_; + data = data_; diff --git a/SOURCES/tigervnc-CVE-2019-15693.patch b/SOURCES/tigervnc-CVE-2019-15693.patch new file mode 100644 index 0000000..1e5f152 --- /dev/null +++ b/SOURCES/tigervnc-CVE-2019-15693.patch @@ -0,0 +1,75 @@ +From b4ada8d0c6dac98c8b91fc64d112569a8ae5fb95 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 10 Sep 2019 15:36:42 +0200 +Subject: [PATCH] Handle empty Tight gradient rects + +We always assumed there would be one pixel per row so a rect with +a zero width would result in us writing to unknown memory. + +This could theoretically be used by a malicious server to inject +code in to the viewer process. + +Issue found by Pavel Cheremushkin from Kaspersky Lab. +--- + common/rfb/tightDecode.h | 37 +++++++++++++++++++++---------------- + 1 file changed, 21 insertions(+), 16 deletions(-) + +diff --git a/common/rfb/tightDecode.h b/common/rfb/tightDecode.h +index b6e86ed5e..8f77aebd0 100644 +--- a/common/rfb/tightDecode.h ++++ b/common/rfb/tightDecode.h +@@ -56,15 +56,17 @@ TightDecoder::FilterGradient24(const rdr::U8 *inbuf, + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { +- /* First pixel in a row */ +- for (c = 0; c < 3; c++) { +- pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c]; +- thisRow[c] = pix[c]; +- } +- pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); ++ for (x = 0; x < rectWidth; x++) { ++ /* First pixel in a row */ ++ if (x == 0) { ++ for (c = 0; c < 3; c++) { ++ pix[c] = inbuf[y*rectWidth*3+c] + prevRow[c]; ++ thisRow[c] = pix[c]; ++ } ++ pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); ++ continue; ++ } + +- /* Remaining pixels of a row */ +- for (x = 1; x < rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 0xff) { +@@ -103,17 +105,20 @@ void TightDecoder::FilterGradient(const rdr::U8* inbuf, + int rectWidth = r.width(); + + for (y = 0; y < rectHeight; y++) { +- /* First pixel in a row */ +- pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1); +- for (c = 0; c < 3; c++) +- pix[c] += prevRow[c]; ++ for (x = 0; x < rectWidth; x++) { ++ /* First pixel in a row */ ++ if (x == 0) { ++ pf.rgbFromBuffer(pix, &inbuf[y*rectWidth], 1); ++ for (c = 0; c < 3; c++) ++ pix[c] += prevRow[c]; + +- memcpy(thisRow, pix, sizeof(pix)); ++ memcpy(thisRow, pix, sizeof(pix)); + +- pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); ++ pf.bufferFromRGB((rdr::U8*)&outbuf[y*stride], pix, 1); ++ ++ continue; ++ } + +- /* Remaining pixels of a row */ +- for (x = 1; x < rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c]; + if (est[c] > 255) { diff --git a/SOURCES/tigervnc-CVE-2019-15694.patch b/SOURCES/tigervnc-CVE-2019-15694.patch new file mode 100644 index 0000000..6f5b729 --- /dev/null +++ b/SOURCES/tigervnc-CVE-2019-15694.patch @@ -0,0 +1,1418 @@ +From 0943c006c7d900dfc0281639e992791d6c567438 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Mon, 23 Sep 2019 11:00:17 +0200 +Subject: [PATCH] Use size_t for lengths in stream objects + +Provides safety against them accidentally becoming negative because +of bugs in the calculations. + +Also does the same to CharArray and friends as they were strongly +connection to the stream objects. +--- + common/rdr/FdInStream.cxx | 20 ++++++++++---------- + common/rdr/FdInStream.h | 17 +++++++++-------- + common/rdr/FdOutStream.cxx | 20 ++++++++++---------- + common/rdr/FdOutStream.h | 12 ++++++------ + common/rdr/FileInStream.cxx | 8 ++++---- + common/rdr/FileInStream.h | 4 ++-- + common/rdr/HexInStream.cxx | 20 ++++++++++---------- + common/rdr/HexInStream.h | 12 ++++++------ + common/rdr/HexOutStream.cxx | 20 ++++++++++---------- + common/rdr/HexOutStream.h | 12 ++++++------ + common/rdr/InStream.h | 16 ++++++++-------- + common/rdr/MemInStream.h | 8 ++++---- + common/rdr/MemOutStream.h | 12 ++++++------ + common/rdr/OutStream.h | 20 ++++++++++---------- + common/rdr/RandomStream.cxx | 14 +++++++------- + common/rdr/RandomStream.h | 6 +++--- + common/rdr/TLSInStream.cxx | 10 +++++----- + common/rdr/TLSInStream.h | 10 +++++----- + common/rdr/TLSOutStream.cxx | 10 +++++----- + common/rdr/TLSOutStream.h | 10 +++++----- + common/rdr/ZlibInStream.cxx | 16 ++++++++-------- + common/rdr/ZlibInStream.h | 14 +++++++------- + common/rdr/ZlibOutStream.cxx | 10 +++++----- + common/rdr/ZlibOutStream.h | 10 +++++----- + common/rfb/Configuration.cxx | 6 +++--- + common/rfb/Configuration.h | 13 +++++++------ + common/rfb/Password.cxx | 6 +++--- + common/rfb/Password.h | 6 +++--- + common/rfb/util.h | 2 +- + tests/perf/encperf.cxx | 10 +++++----- + win/rfb_win32/Registry.cxx | 6 +++--- + win/rfb_win32/Registry.h | 6 +++--- + 32 files changed, 184 insertions(+), 182 deletions(-) + +diff --git a/common/rdr/FdInStream.cxx b/common/rdr/FdInStream.cxx +index a8b3085..e99c108 100644 +--- a/common/rdr/FdInStream.cxx ++++ b/common/rdr/FdInStream.cxx +@@ -56,7 +56,7 @@ using namespace rdr; + enum { DEFAULT_BUF_SIZE = 8192, + MIN_BULK_SIZE = 1024 }; + +-FdInStream::FdInStream(int fd_, int timeoutms_, int bufSize_, ++FdInStream::FdInStream(int fd_, int timeoutms_, size_t bufSize_, + bool closeWhenDone_) + : fd(fd_), closeWhenDone(closeWhenDone_), + timeoutms(timeoutms_), blockCallback(0), +@@ -67,7 +67,7 @@ FdInStream::FdInStream(int fd_, int timeoutms_, int bufSize_, + } + + FdInStream::FdInStream(int fd_, FdInStreamBlockCallback* blockCallback_, +- int bufSize_) ++ size_t bufSize_) + : fd(fd_), timeoutms(0), blockCallback(blockCallback_), + timing(false), timeWaitedIn100us(5), timedKbits(0), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) +@@ -92,12 +92,12 @@ void FdInStream::setBlockCallback(FdInStreamBlockCallback* blockCallback_) + timeoutms = 0; + } + +-int FdInStream::pos() ++size_t FdInStream::pos() + { + return offset + ptr - start; + } + +-void FdInStream::readBytes(void* data, int length) ++void FdInStream::readBytes(void* data, size_t length) + { + if (length < MIN_BULK_SIZE) { + InStream::readBytes(data, length); +@@ -106,7 +106,7 @@ void FdInStream::readBytes(void* data, int length) + + U8* dataPtr = (U8*)data; + +- int n = end - ptr; ++ size_t n = end - ptr; + if (n > length) n = length; + + memcpy(dataPtr, ptr, n); +@@ -123,7 +123,7 @@ void FdInStream::readBytes(void* data, int length) + } + + +-int FdInStream::overrun(int itemSize, int nItems, bool wait) ++size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait) + { + if (itemSize > bufSize) + throw Exception("FdInStream overrun: max itemSize exceeded"); +@@ -135,7 +135,7 @@ int FdInStream::overrun(int itemSize, int nItems, bool wait) + end -= ptr - start; + ptr = start; + +- int bytes_to_read; ++ size_t bytes_to_read; + while (end < start + itemSize) { + bytes_to_read = start + bufSize - end; + if (!timing) { +@@ -147,12 +147,12 @@ int FdInStream::overrun(int itemSize, int nItems, bool wait) + // bytes is ineffecient. + bytes_to_read = vncmin(bytes_to_read, vncmax(itemSize*nItems, 8)); + } +- int n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait); ++ size_t n = readWithTimeoutOrCallback((U8*)end, bytes_to_read, wait); + if (n == 0) return 0; + end += n; + } + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +@@ -171,7 +171,7 @@ int FdInStream::overrun(int itemSize, int nItems, bool wait) + // returning EINTR. + // + +-int FdInStream::readWithTimeoutOrCallback(void* buf, int len, bool wait) ++size_t FdInStream::readWithTimeoutOrCallback(void* buf, size_t len, bool wait) + { + struct timeval before, after; + if (timing) +diff --git a/common/rdr/FdInStream.h b/common/rdr/FdInStream.h +index 5d9598c..b93fd84 100644 +--- a/common/rdr/FdInStream.h ++++ b/common/rdr/FdInStream.h +@@ -36,16 +36,17 @@ namespace rdr { + + public: + +- FdInStream(int fd, int timeoutms=-1, int bufSize=0, ++ FdInStream(int fd, int timeoutms=-1, size_t bufSize=0, + bool closeWhenDone_=false); +- FdInStream(int fd, FdInStreamBlockCallback* blockCallback, int bufSize=0); ++ FdInStream(int fd, FdInStreamBlockCallback* blockCallback, ++ size_t bufSize=0); + virtual ~FdInStream(); + + void setTimeout(int timeoutms); + void setBlockCallback(FdInStreamBlockCallback* blockCallback); + int getFd() { return fd; } +- int pos(); +- void readBytes(void* data, int length); ++ size_t pos(); ++ void readBytes(void* data, size_t length); + + void startTiming(); + void stopTiming(); +@@ -53,10 +54,10 @@ namespace rdr { + unsigned int timeWaited() { return timeWaitedIn100us; } + + protected: +- int overrun(int itemSize, int nItems, bool wait); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait); + + private: +- int readWithTimeoutOrCallback(void* buf, int len, bool wait=true); ++ size_t readWithTimeoutOrCallback(void* buf, size_t len, bool wait=true); + + int fd; + bool closeWhenDone; +@@ -67,8 +68,8 @@ namespace rdr { + unsigned int timeWaitedIn100us; + unsigned int timedKbits; + +- int bufSize; +- int offset; ++ size_t bufSize; ++ size_t offset; + U8* start; + }; + +diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx +index 29e864f..0900fd1 100644 +--- a/common/rdr/FdOutStream.cxx ++++ b/common/rdr/FdOutStream.cxx +@@ -50,7 +50,7 @@ using namespace rdr; + + enum { DEFAULT_BUF_SIZE = 16384 }; + +-FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, int bufSize_) ++FdOutStream::FdOutStream(int fd_, bool blocking_, int timeoutms_, size_t bufSize_) + : fd(fd_), blocking(blocking_), timeoutms(timeoutms_), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) + { +@@ -78,7 +78,7 @@ void FdOutStream::setBlocking(bool blocking_) { + blocking = blocking_; + } + +-int FdOutStream::length() ++size_t FdOutStream::length() + { + return offset + ptr - sentUpTo; + } +@@ -96,9 +96,9 @@ unsigned FdOutStream::getIdleTime() + void FdOutStream::flush() + { + while (sentUpTo < ptr) { +- int n = writeWithTimeout((const void*) sentUpTo, +- ptr - sentUpTo, +- blocking? timeoutms : 0); ++ size_t n = writeWithTimeout((const void*) sentUpTo, ++ ptr - sentUpTo, ++ blocking? timeoutms : 0); + + // Timeout? + if (n == 0) { +@@ -119,7 +119,7 @@ void FdOutStream::flush() + } + + +-int FdOutStream::overrun(int itemSize, int nItems) ++size_t FdOutStream::overrun(size_t itemSize, size_t nItems) + { + if (itemSize > bufSize) + throw Exception("FdOutStream overrun: max itemSize exceeded"); +@@ -128,10 +128,10 @@ int FdOutStream::overrun(int itemSize, int nItems) + flush(); + + // Still not enough space? +- if (itemSize > end - ptr) { ++ if (itemSize > (size_t)(end - ptr)) { + // Can we shuffle things around? + // (don't do this if it gains us less than 25%) +- if ((sentUpTo - start > bufSize / 4) && ++ if (((size_t)(sentUpTo - start) > bufSize / 4) && + (itemSize < bufSize - (ptr - sentUpTo))) { + memmove(start, sentUpTo, ptr - sentUpTo); + ptr = start + (ptr - sentUpTo); +@@ -149,7 +149,7 @@ int FdOutStream::overrun(int itemSize, int nItems) + } + + // Can we fit all the items asked for? +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +@@ -165,7 +165,7 @@ int FdOutStream::overrun(int itemSize, int nItems) + // select() and write() returning EINTR. + // + +-int FdOutStream::writeWithTimeout(const void* data, int length, int timeoutms) ++size_t FdOutStream::writeWithTimeout(const void* data, size_t length, int timeoutms) + { + int n; + +diff --git a/common/rdr/FdOutStream.h b/common/rdr/FdOutStream.h +index b7f6cb0..ed84fdb 100644 +--- a/common/rdr/FdOutStream.h ++++ b/common/rdr/FdOutStream.h +@@ -34,7 +34,7 @@ namespace rdr { + + public: + +- FdOutStream(int fd, bool blocking=true, int timeoutms=-1, int bufSize=0); ++ FdOutStream(int fd, bool blocking=true, int timeoutms=-1, size_t bufSize=0); + virtual ~FdOutStream(); + + void setTimeout(int timeoutms); +@@ -42,20 +42,20 @@ namespace rdr { + int getFd() { return fd; } + + void flush(); +- int length(); ++ size_t length(); + + int bufferUsage(); + + unsigned getIdleTime(); + + private: +- int overrun(int itemSize, int nItems); +- int writeWithTimeout(const void* data, int length, int timeoutms); ++ size_t overrun(size_t itemSize, size_t nItems); ++ size_t writeWithTimeout(const void* data, size_t length, int timeoutms); + int fd; + bool blocking; + int timeoutms; +- int bufSize; +- int offset; ++ size_t bufSize; ++ size_t offset; + U8* start; + U8* sentUpTo; + struct timeval lastWrite; +diff --git a/common/rdr/FileInStream.cxx b/common/rdr/FileInStream.cxx +index 8d5c22e..56830a0 100644 +--- a/common/rdr/FileInStream.cxx ++++ b/common/rdr/FileInStream.cxx +@@ -48,7 +48,7 @@ void FileInStream::reset(void) { + ptr = end = b; + } + +-int FileInStream::pos() ++size_t FileInStream::pos() + { + if (!file) + throw Exception("File is not open"); +@@ -56,9 +56,9 @@ int FileInStream::pos() + return ftell(file) + ptr - b; + } + +-int FileInStream::overrun(int itemSize, int nItems, bool wait) ++size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait) + { +- if (itemSize > (int)sizeof(b)) ++ if (itemSize > sizeof(b)) + throw Exception("FileInStream overrun: max itemSize exceeded"); + + if (end - ptr != 0) +@@ -80,7 +80,7 @@ int FileInStream::overrun(int itemSize, int nItems, bool wait) + end += b + sizeof(b) - end; + } + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +diff --git a/common/rdr/FileInStream.h b/common/rdr/FileInStream.h +index ace04f3..a33c765 100644 +--- a/common/rdr/FileInStream.h ++++ b/common/rdr/FileInStream.h +@@ -35,10 +35,10 @@ namespace rdr { + + void reset(void); + +- int pos(); ++ size_t pos(); + + protected: +- int overrun(int itemSize, int nItems, bool wait = true); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait = true); + + private: + U8 b[131072]; +diff --git a/common/rdr/HexInStream.cxx b/common/rdr/HexInStream.cxx +index 80f8a79..8f93988 100644 +--- a/common/rdr/HexInStream.cxx ++++ b/common/rdr/HexInStream.cxx +@@ -28,7 +28,7 @@ const int DEFAULT_BUF_LEN = 16384; + + static inline int min(int a, int b) {return a bufSize) + throw Exception("HexInStream overrun: max itemSize exceeded"); + +@@ -92,14 +92,14 @@ int HexInStream::overrun(int itemSize, int nItems, bool wait) { + ptr = start; + + while (end < ptr + itemSize) { +- int n = in_stream.check(2, 1, wait); ++ size_t n = in_stream.check(2, 1, wait); + if (n == 0) return 0; + const U8* iptr = in_stream.getptr(); + const U8* eptr = in_stream.getend(); +- int length = min((eptr - iptr)/2, start + bufSize - end); ++ size_t length = min((eptr - iptr)/2, start + bufSize - end); + + U8* optr = (U8*) end; +- for (int i=0; i end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +diff --git a/common/rdr/HexInStream.h b/common/rdr/HexInStream.h +index 6bfb843..8e495fb 100644 +--- a/common/rdr/HexInStream.h ++++ b/common/rdr/HexInStream.h +@@ -26,21 +26,21 @@ namespace rdr { + class HexInStream : public InStream { + public: + +- HexInStream(InStream& is, int bufSize=0); ++ HexInStream(InStream& is, size_t bufSize=0); + virtual ~HexInStream(); + +- int pos(); ++ size_t pos(); + + static bool readHexAndShift(char c, int* v); +- static bool hexStrToBin(const char* s, char** data, int* length); ++ static bool hexStrToBin(const char* s, char** data, size_t* length); + + protected: +- int overrun(int itemSize, int nItems, bool wait); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait); + + private: +- int bufSize; ++ size_t bufSize; + U8* start; +- int offset; ++ size_t offset; + + InStream& in_stream; + }; +diff --git a/common/rdr/HexOutStream.cxx b/common/rdr/HexOutStream.cxx +index 9b0b6c4..7232514 100644 +--- a/common/rdr/HexOutStream.cxx ++++ b/common/rdr/HexOutStream.cxx +@@ -23,9 +23,9 @@ using namespace rdr; + + const int DEFAULT_BUF_LEN = 16384; + +-static inline int min(int a, int b) {return a> 4) & 15); + buffer[i*2+1] = intToHex((data[i] & 15)); + if (!buffer[i*2] || !buffer[i*2+1]) { +@@ -70,9 +70,9 @@ HexOutStream::writeBuffer() { + out_stream.check(2); + U8* optr = out_stream.getptr(); + U8* oend = out_stream.getend(); +- int length = min(ptr-pos, (oend-optr)/2); ++ size_t length = min(ptr-pos, (oend-optr)/2); + +- for (int i=0; i> 4) & 0xf); + optr[i*2+1] = intToHex(pos[i] & 0xf); + } +@@ -84,7 +84,7 @@ HexOutStream::writeBuffer() { + ptr = start; + } + +-int HexOutStream::length() ++size_t HexOutStream::length() + { + return offset + ptr - start; + } +@@ -95,14 +95,14 @@ HexOutStream::flush() { + out_stream.flush(); + } + +-int +-HexOutStream::overrun(int itemSize, int nItems) { ++size_t ++HexOutStream::overrun(size_t itemSize, size_t nItems) { + if (itemSize > bufSize) + throw Exception("HexOutStream overrun: max itemSize exceeded"); + + writeBuffer(); + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +diff --git a/common/rdr/HexOutStream.h b/common/rdr/HexOutStream.h +index 10247e6..92442a7 100644 +--- a/common/rdr/HexOutStream.h ++++ b/common/rdr/HexOutStream.h +@@ -26,24 +26,24 @@ namespace rdr { + class HexOutStream : public OutStream { + public: + +- HexOutStream(OutStream& os, int buflen=0); ++ HexOutStream(OutStream& os, size_t buflen=0); + virtual ~HexOutStream(); + + void flush(); +- int length(); ++ size_t length(); + + static char intToHex(int i); +- static char* binToHexStr(const char* data, int length); ++ static char* binToHexStr(const char* data, size_t length); + + private: + void writeBuffer(); +- int overrun(int itemSize, int nItems); ++ size_t overrun(size_t itemSize, size_t nItems); + + OutStream& out_stream; + + U8* start; +- int offset; +- int bufSize; ++ size_t offset; ++ size_t bufSize; + }; + + } +diff --git a/common/rdr/InStream.h b/common/rdr/InStream.h +index 212a2ec..14ecf09 100644 +--- a/common/rdr/InStream.h ++++ b/common/rdr/InStream.h +@@ -41,7 +41,7 @@ namespace rdr { + // for the bytes, zero is returned if the bytes are not immediately + // available. + +- inline int check(int itemSize, int nItems=1, bool wait=true) ++ inline size_t check(size_t itemSize, size_t nItems=1, bool wait=true) + { + if (ptr + itemSize * nItems > end) { + if (ptr + itemSize > end) +@@ -56,7 +56,7 @@ namespace rdr { + // be read without blocking. It returns true if this is the case, false + // otherwise. The length must be "small" (less than the buffer size). + +- inline bool checkNoWait(int length) { return check(length, 1, false)!=0; } ++ inline bool checkNoWait(size_t length) { return check(length, 1, false)!=0; } + + // readU/SN() methods read unsigned and signed N-bit integers. + +@@ -82,9 +82,9 @@ namespace rdr { + + static U32 maxStringLength; + +- inline void skip(int bytes) { ++ inline void skip(size_t bytes) { + while (bytes > 0) { +- int n = check(1, bytes); ++ size_t n = check(1, bytes); + ptr += n; + bytes -= n; + } +@@ -92,11 +92,11 @@ namespace rdr { + + // readBytes() reads an exact number of bytes. + +- void readBytes(void* data, int length) { ++ void readBytes(void* data, size_t length) { + U8* dataPtr = (U8*)data; + U8* dataEnd = dataPtr + length; + while (dataPtr < dataEnd) { +- int n = check(1, dataEnd - dataPtr); ++ size_t n = check(1, dataEnd - dataPtr); + memcpy(dataPtr, ptr, n); + ptr += n; + dataPtr += n; +@@ -114,7 +114,7 @@ namespace rdr { + + // pos() returns the position in the stream. + +- virtual int pos() = 0; ++ virtual size_t pos() = 0; + + // getptr(), getend() and setptr() are "dirty" methods which allow you to + // manipulate the buffer directly. This is useful for a stream which is a +@@ -133,7 +133,7 @@ namespace rdr { + // instead of blocking to wait for the bytes, zero is returned if the bytes + // are not immediately available. + +- virtual int overrun(int itemSize, int nItems, bool wait=true) = 0; ++ virtual size_t overrun(size_t itemSize, size_t nItems, bool wait=true) = 0; + + protected: + +diff --git a/common/rdr/MemInStream.h b/common/rdr/MemInStream.h +index 1a6a798..3e9e77b 100644 +--- a/common/rdr/MemInStream.h ++++ b/common/rdr/MemInStream.h +@@ -36,7 +36,7 @@ namespace rdr { + + public: + +- MemInStream(const void* data, int len, bool deleteWhenDone_=false) ++ MemInStream(const void* data, size_t len, bool deleteWhenDone_=false) + : start((const U8*)data), deleteWhenDone(deleteWhenDone_) + { + ptr = start; +@@ -48,12 +48,12 @@ namespace rdr { + delete [] start; + } + +- int pos() { return ptr - start; } +- void reposition(int pos) { ptr = start + pos; } ++ size_t pos() { return ptr - start; } ++ void reposition(size_t pos) { ptr = start + pos; } + + private: + +- int overrun(int itemSize, int nItems, bool wait) { throw EndOfStream(); } ++ size_t overrun(size_t itemSize, size_t nItems, bool wait) { throw EndOfStream(); } + const U8* start; + bool deleteWhenDone; + }; +diff --git a/common/rdr/MemOutStream.h b/common/rdr/MemOutStream.h +index 3b17e55..4a815b3 100644 +--- a/common/rdr/MemOutStream.h ++++ b/common/rdr/MemOutStream.h +@@ -40,16 +40,16 @@ namespace rdr { + delete [] start; + } + +- void writeBytes(const void* data, int length) { ++ void writeBytes(const void* data, size_t length) { + check(length); + memcpy(ptr, data, length); + ptr += length; + } + +- int length() { return ptr - start; } ++ size_t length() { return ptr - start; } + void clear() { ptr = start; }; + void clearAndZero() { memset(start, 0, ptr-start); clear(); } +- void reposition(int pos) { ptr = start + pos; } ++ void reposition(size_t pos) { ptr = start + pos; } + + // data() returns a pointer to the buffer. + +@@ -60,9 +60,9 @@ namespace rdr { + // overrun() either doubles the buffer or adds enough space for nItems of + // size itemSize bytes. + +- int overrun(int itemSize, int nItems) { +- int len = ptr - start + itemSize * nItems; +- if (len < (end - start) * 2) ++ size_t overrun(size_t itemSize, size_t nItems) { ++ size_t len = ptr - start + itemSize * nItems; ++ if (len < (size_t)(end - start) * 2) + len = (end - start) * 2; + + U8* newStart = new U8[len]; +diff --git a/common/rdr/OutStream.h b/common/rdr/OutStream.h +index a749a20..11aafd2 100644 +--- a/common/rdr/OutStream.h ++++ b/common/rdr/OutStream.h +@@ -44,7 +44,7 @@ namespace rdr { + // itemSize bytes. Returns the number of items which fit (up to a maximum + // of nItems). + +- inline int check(int itemSize, int nItems=1) ++ inline size_t check(size_t itemSize, size_t nItems=1) + { + if (ptr + itemSize * nItems > end) { + if (ptr + itemSize > end) +@@ -76,13 +76,13 @@ namespace rdr { + writeBytes(str, len); + } + +- inline void pad(int bytes) { ++ inline void pad(size_t bytes) { + while (bytes-- > 0) writeU8(0); + } + +- inline void skip(int bytes) { ++ inline void skip(size_t bytes) { + while (bytes > 0) { +- int n = check(1, bytes); ++ size_t n = check(1, bytes); + ptr += n; + bytes -= n; + } +@@ -90,11 +90,11 @@ namespace rdr { + + // writeBytes() writes an exact number of bytes. + +- void writeBytes(const void* data, int length) { ++ void writeBytes(const void* data, size_t length) { + const U8* dataPtr = (const U8*)data; + const U8* dataEnd = dataPtr + length; + while (dataPtr < dataEnd) { +- int n = check(1, dataEnd - dataPtr); ++ size_t n = check(1, dataEnd - dataPtr); + memcpy(ptr, dataPtr, n); + ptr += n; + dataPtr += n; +@@ -103,9 +103,9 @@ namespace rdr { + + // copyBytes() efficiently transfers data between streams + +- void copyBytes(InStream* is, int length) { ++ void copyBytes(InStream* is, size_t length) { + while (length > 0) { +- int n = check(1, length); ++ size_t n = check(1, length); + is->readBytes(ptr, n); + ptr += n; + length -= n; +@@ -124,7 +124,7 @@ namespace rdr { + + // length() returns the length of the stream. + +- virtual int length() = 0; ++ virtual size_t length() = 0; + + // flush() requests that the stream be flushed. + +@@ -145,7 +145,7 @@ namespace rdr { + // the number of items which fit (up to a maximum of nItems). itemSize is + // supposed to be "small" (a few bytes). + +- virtual int overrun(int itemSize, int nItems) = 0; ++ virtual size_t overrun(size_t itemSize, size_t nItems) = 0; + + protected: + +diff --git a/common/rdr/RandomStream.cxx b/common/rdr/RandomStream.cxx +index 3fde18d..7681095 100644 +--- a/common/rdr/RandomStream.cxx ++++ b/common/rdr/RandomStream.cxx +@@ -32,7 +32,7 @@ + + using namespace rdr; + +-const int DEFAULT_BUF_LEN = 256; ++const size_t DEFAULT_BUF_LEN = 256; + + unsigned int RandomStream::seed; + +@@ -83,11 +83,11 @@ RandomStream::~RandomStream() { + #endif + } + +-int RandomStream::pos() { ++size_t RandomStream::pos() { + return offset + ptr - start; + } + +-int RandomStream::overrun(int itemSize, int nItems, bool wait) { ++size_t RandomStream::overrun(size_t itemSize, size_t nItems, bool wait) { + if (itemSize > DEFAULT_BUF_LEN) + throw Exception("RandomStream overrun: max itemSize exceeded"); + +@@ -98,7 +98,7 @@ int RandomStream::overrun(int itemSize, int nItems, bool wait) { + offset += ptr - start; + ptr = start; + +- int length = start + DEFAULT_BUF_LEN - end; ++ size_t length = start + DEFAULT_BUF_LEN - end; + + #ifdef RFB_HAVE_WINCRYPT + if (provider) { +@@ -109,7 +109,7 @@ int RandomStream::overrun(int itemSize, int nItems, bool wait) { + #else + #ifndef WIN32 + if (fp) { +- int n = fread((U8*)end, length, 1, fp); ++ size_t n = fread((U8*)end, length, 1, fp); + if (n != 1) + throw rdr::SystemException("reading /dev/urandom or /dev/random failed", + errno); +@@ -119,11 +119,11 @@ int RandomStream::overrun(int itemSize, int nItems, bool wait) { + { + #endif + #endif +- for (int i=0; i end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +diff --git a/common/rdr/RandomStream.h b/common/rdr/RandomStream.h +index c33360d..80b389b 100644 +--- a/common/rdr/RandomStream.h ++++ b/common/rdr/RandomStream.h +@@ -39,14 +39,14 @@ namespace rdr { + RandomStream(); + virtual ~RandomStream(); + +- int pos(); ++ size_t pos(); + + protected: +- int overrun(int itemSize, int nItems, bool wait); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait); + + private: + U8* start; +- int offset; ++ size_t offset; + + static unsigned int seed; + #ifdef RFB_HAVE_WINCRYPT +diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx +index 77b1672..d0f9426 100644 +--- a/common/rdr/TLSInStream.cxx ++++ b/common/rdr/TLSInStream.cxx +@@ -75,12 +75,12 @@ TLSInStream::~TLSInStream() + delete[] start; + } + +-int TLSInStream::pos() ++size_t TLSInStream::pos() + { + return offset + ptr - start; + } + +-int TLSInStream::overrun(int itemSize, int nItems, bool wait) ++size_t TLSInStream::overrun(size_t itemSize, size_t nItems, bool wait) + { + if (itemSize > bufSize) + throw Exception("TLSInStream overrun: max itemSize exceeded"); +@@ -93,19 +93,19 @@ int TLSInStream::overrun(int itemSize, int nItems, bool wait) + ptr = start; + + while (end < start + itemSize) { +- int n = readTLS((U8*) end, start + bufSize - end, wait); ++ size_t n = readTLS((U8*) end, start + bufSize - end, wait); + if (!wait && n == 0) + return 0; + end += n; + } + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; + } + +-int TLSInStream::readTLS(U8* buf, int len, bool wait) ++size_t TLSInStream::readTLS(U8* buf, size_t len, bool wait) + { + int n; + +diff --git a/common/rdr/TLSInStream.h b/common/rdr/TLSInStream.h +index b16d9f5..5f9dee7 100644 +--- a/common/rdr/TLSInStream.h ++++ b/common/rdr/TLSInStream.h +@@ -36,17 +36,17 @@ namespace rdr { + TLSInStream(InStream* in, gnutls_session_t session); + virtual ~TLSInStream(); + +- int pos(); ++ size_t pos(); + + private: +- int overrun(int itemSize, int nItems, bool wait); +- int readTLS(U8* buf, int len, bool wait); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait); ++ size_t readTLS(U8* buf, size_t len, bool wait); + static ssize_t pull(gnutls_transport_ptr_t str, void* data, size_t size); + + gnutls_session_t session; + InStream* in; +- int bufSize; +- int offset; ++ size_t bufSize; ++ size_t offset; + U8* start; + }; + }; +diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx +index 44d2d9f..30c456f 100644 +--- a/common/rdr/TLSOutStream.cxx ++++ b/common/rdr/TLSOutStream.cxx +@@ -75,7 +75,7 @@ TLSOutStream::~TLSOutStream() + delete [] start; + } + +-int TLSOutStream::length() ++size_t TLSOutStream::length() + { + return offset + ptr - start; + } +@@ -84,7 +84,7 @@ void TLSOutStream::flush() + { + U8* sentUpTo = start; + while (sentUpTo < ptr) { +- int n = writeTLS(sentUpTo, ptr - sentUpTo); ++ size_t n = writeTLS(sentUpTo, ptr - sentUpTo); + sentUpTo += n; + offset += n; + } +@@ -93,20 +93,20 @@ void TLSOutStream::flush() + out->flush(); + } + +-int TLSOutStream::overrun(int itemSize, int nItems) ++size_t TLSOutStream::overrun(size_t itemSize, size_t nItems) + { + if (itemSize > bufSize) + throw Exception("TLSOutStream overrun: max itemSize exceeded"); + + flush(); + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; + } + +-int TLSOutStream::writeTLS(const U8* data, int length) ++size_t TLSOutStream::writeTLS(const U8* data, size_t length) + { + int n; + +diff --git a/common/rdr/TLSOutStream.h b/common/rdr/TLSOutStream.h +index 81dd237..71a7f3b 100644 +--- a/common/rdr/TLSOutStream.h ++++ b/common/rdr/TLSOutStream.h +@@ -36,20 +36,20 @@ namespace rdr { + virtual ~TLSOutStream(); + + void flush(); +- int length(); ++ size_t length(); + + protected: +- int overrun(int itemSize, int nItems); ++ size_t overrun(size_t itemSize, size_t nItems); + + private: +- int writeTLS(const U8* data, int length); ++ size_t writeTLS(const U8* data, size_t length); + static ssize_t push(gnutls_transport_ptr_t str, const void* data, size_t size); + + gnutls_session_t session; + OutStream* out; +- int bufSize; ++ size_t bufSize; + U8* start; +- int offset; ++ size_t offset; + }; + }; + +diff --git a/common/rdr/ZlibInStream.cxx b/common/rdr/ZlibInStream.cxx +index a361010..e2f971c 100644 +--- a/common/rdr/ZlibInStream.cxx ++++ b/common/rdr/ZlibInStream.cxx +@@ -26,7 +26,7 @@ using namespace rdr; + + enum { DEFAULT_BUF_SIZE = 16384 }; + +-ZlibInStream::ZlibInStream(int bufSize_) ++ZlibInStream::ZlibInStream(size_t bufSize_) + : underlying(0), bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0), + zs(NULL), bytesIn(0) + { +@@ -40,14 +40,14 @@ ZlibInStream::~ZlibInStream() + delete [] start; + } + +-void ZlibInStream::setUnderlying(InStream* is, int bytesIn_) ++void ZlibInStream::setUnderlying(InStream* is, size_t bytesIn_) + { + underlying = is; + bytesIn = bytesIn_; + ptr = end = start; + } + +-int ZlibInStream::pos() ++size_t ZlibInStream::pos() + { + return offset + ptr - start; + } +@@ -96,7 +96,7 @@ void ZlibInStream::deinit() + zs = NULL; + } + +-int ZlibInStream::overrun(int itemSize, int nItems, bool wait) ++size_t ZlibInStream::overrun(size_t itemSize, size_t nItems, bool wait) + { + if (itemSize > bufSize) + throw Exception("ZlibInStream overrun: max itemSize exceeded"); +@@ -108,12 +108,12 @@ int ZlibInStream::overrun(int itemSize, int nItems, bool wait) + end -= ptr - start; + ptr = start; + +- while (end - ptr < itemSize) { ++ while ((size_t)(end - ptr) < itemSize) { + if (!decompress(wait)) + return 0; + } + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +@@ -131,11 +131,11 @@ bool ZlibInStream::decompress(bool wait) + zs->next_out = (U8*)end; + zs->avail_out = start + bufSize - end; + +- int n = underlying->check(1, 1, wait); ++ size_t n = underlying->check(1, 1, wait); + if (n == 0) return false; + zs->next_in = (U8*)underlying->getptr(); + zs->avail_in = underlying->getend() - underlying->getptr(); +- if ((int)zs->avail_in > bytesIn) ++ if (zs->avail_in > bytesIn) + zs->avail_in = bytesIn; + + int rc = inflate(zs, Z_SYNC_FLUSH); +diff --git a/common/rdr/ZlibInStream.h b/common/rdr/ZlibInStream.h +index 86ba1ff..08784b0 100644 +--- a/common/rdr/ZlibInStream.h ++++ b/common/rdr/ZlibInStream.h +@@ -34,12 +34,12 @@ namespace rdr { + + public: + +- ZlibInStream(int bufSize=0); ++ ZlibInStream(size_t bufSize=0); + virtual ~ZlibInStream(); + +- void setUnderlying(InStream* is, int bytesIn); ++ void setUnderlying(InStream* is, size_t bytesIn); + void flushUnderlying(); +- int pos(); ++ size_t pos(); + void reset(); + + private: +@@ -47,14 +47,14 @@ namespace rdr { + void init(); + void deinit(); + +- int overrun(int itemSize, int nItems, bool wait); ++ size_t overrun(size_t itemSize, size_t nItems, bool wait); + bool decompress(bool wait); + + InStream* underlying; +- int bufSize; +- int offset; ++ size_t bufSize; ++ size_t offset; + z_stream_s* zs; +- int bytesIn; ++ size_t bytesIn; + U8* start; + }; + +diff --git a/common/rdr/ZlibOutStream.cxx b/common/rdr/ZlibOutStream.cxx +index 9d9f8ba..4e7ffd6 100644 +--- a/common/rdr/ZlibOutStream.cxx ++++ b/common/rdr/ZlibOutStream.cxx +@@ -30,7 +30,7 @@ using namespace rdr; + + enum { DEFAULT_BUF_SIZE = 16384 }; + +-ZlibOutStream::ZlibOutStream(OutStream* os, int bufSize_, int compressLevel) ++ZlibOutStream::ZlibOutStream(OutStream* os, size_t bufSize_, int compressLevel) + : underlying(os), compressionLevel(compressLevel), newLevel(compressLevel), + bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_SIZE), offset(0) + { +@@ -72,7 +72,7 @@ void ZlibOutStream::setCompressionLevel(int level) + newLevel = level; + } + +-int ZlibOutStream::length() ++size_t ZlibOutStream::length() + { + return offset + ptr - start; + } +@@ -95,7 +95,7 @@ void ZlibOutStream::flush() + ptr = start; + } + +-int ZlibOutStream::overrun(int itemSize, int nItems) ++size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems) + { + #ifdef ZLIBOUT_DEBUG + fprintf(stderr,"zos overrun\n"); +@@ -106,7 +106,7 @@ int ZlibOutStream::overrun(int itemSize, int nItems) + + checkCompressionLevel(); + +- while (end - ptr < itemSize) { ++ while ((size_t)(end - ptr) < itemSize) { + zs->next_in = start; + zs->avail_in = ptr - start; + +@@ -127,7 +127,7 @@ int ZlibOutStream::overrun(int itemSize, int nItems) + } + } + +- if (itemSize * nItems > end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + + return nItems; +diff --git a/common/rdr/ZlibOutStream.h b/common/rdr/ZlibOutStream.h +index 2d82a13..11bb046 100644 +--- a/common/rdr/ZlibOutStream.h ++++ b/common/rdr/ZlibOutStream.h +@@ -35,25 +35,25 @@ namespace rdr { + + public: + +- ZlibOutStream(OutStream* os=0, int bufSize=0, int compressionLevel=-1); ++ ZlibOutStream(OutStream* os=0, size_t bufSize=0, int compressionLevel=-1); + virtual ~ZlibOutStream(); + + void setUnderlying(OutStream* os); + void setCompressionLevel(int level=-1); + void flush(); +- int length(); ++ size_t length(); + + private: + +- int overrun(int itemSize, int nItems); ++ size_t overrun(size_t itemSize, size_t nItems); + void deflate(int flush); + void checkCompressionLevel(); + + OutStream* underlying; + int compressionLevel; + int newLevel; +- int bufSize; +- int offset; ++ size_t bufSize; ++ size_t offset; + z_stream_s* zs; + U8* start; + }; +diff --git a/common/rfb/Configuration.cxx b/common/rfb/Configuration.cxx +index a5c2302..50ecfb3 100644 +--- a/common/rfb/Configuration.cxx ++++ b/common/rfb/Configuration.cxx +@@ -403,7 +403,7 @@ StringParameter::operator const char *() const { + // -=- BinaryParameter + + BinaryParameter::BinaryParameter(const char* name_, const char* desc_, +- const void* v, int l, ConfigurationObject co) ++ const void* v, size_t l, ConfigurationObject co) + : VoidParameter(name_, desc_, co), value(0), length(0), def_value((char*)v), def_length(l) { + if (l) { + value = new char[l]; +@@ -423,7 +423,7 @@ bool BinaryParameter::setParam(const char* v) { + return rdr::HexInStream::hexStrToBin(v, &value, &length); + } + +-void BinaryParameter::setParam(const void* v, int len) { ++void BinaryParameter::setParam(const void* v, size_t len) { + LOCK_CONFIG; + if (immutable) return; + vlog.debug("set %s(Binary)", getName()); +@@ -444,7 +444,7 @@ char* BinaryParameter::getValueStr() const { + return rdr::HexOutStream::binToHexStr(value, length); + } + +-void BinaryParameter::getData(void** data_, int* length_) const { ++void BinaryParameter::getData(void** data_, size_t* length_) const { + LOCK_CONFIG; + if (length_) *length_ = length; + if (data_) { +diff --git a/common/rfb/Configuration.h b/common/rfb/Configuration.h +index fbf161d..ced726b 100644 +--- a/common/rfb/Configuration.h ++++ b/common/rfb/Configuration.h +@@ -249,23 +249,24 @@ namespace rfb { + + class BinaryParameter : public VoidParameter { + public: +- BinaryParameter(const char* name_, const char* desc_, const void* v, int l, +- ConfigurationObject co=ConfGlobal); ++ BinaryParameter(const char* name_, const char* desc_, ++ const void* v, size_t l, ++ ConfigurationObject co=ConfGlobal); + virtual ~BinaryParameter(); + virtual bool setParam(const char* value); +- virtual void setParam(const void* v, int l); ++ virtual void setParam(const void* v, size_t l); + virtual char* getDefaultStr() const; + virtual char* getValueStr() const; + + // getData() will return length zero if there is no data + // NB: data may be set to zero, OR set to a zero-length buffer +- void getData(void** data, int* length) const; ++ void getData(void** data, size_t* length) const; + + protected: + char* value; +- int length; ++ size_t length; + char* def_value; +- int def_length; ++ size_t def_length; + }; + + // -=- ParameterIterator +diff --git a/common/rfb/Password.cxx b/common/rfb/Password.cxx +index 240c9d4..e4a508c 100644 +--- a/common/rfb/Password.cxx ++++ b/common/rfb/Password.cxx +@@ -38,7 +38,7 @@ PlainPasswd::PlainPasswd() {} + PlainPasswd::PlainPasswd(char* pwd) : CharArray(pwd) { + } + +-PlainPasswd::PlainPasswd(int len) : CharArray(len) { ++PlainPasswd::PlainPasswd(size_t len) : CharArray(len) { + } + + PlainPasswd::PlainPasswd(const ObfuscatedPasswd& obfPwd) : CharArray(9) { +@@ -63,11 +63,11 @@ void PlainPasswd::replaceBuf(char* b) { + ObfuscatedPasswd::ObfuscatedPasswd() : length(0) { + } + +-ObfuscatedPasswd::ObfuscatedPasswd(int len) : CharArray(len), length(len) { ++ObfuscatedPasswd::ObfuscatedPasswd(size_t len) : CharArray(len), length(len) { + } + + ObfuscatedPasswd::ObfuscatedPasswd(const PlainPasswd& plainPwd) : CharArray(8), length(8) { +- int l = strlen(plainPwd.buf), i; ++ size_t l = strlen(plainPwd.buf), i; + for (i=0; i<8; i++) + buf[i] = i end - ptr) ++ if (itemSize * nItems > (size_t)(end - ptr)) + nItems = (end - ptr) / itemSize; + return nItems; + } +diff --git a/common/rdr/SubstitutingInStream.h b/common/rdr/SubstitutingInStream.h +index 325b01c..4acfc04 100644 +--- a/common/rdr/SubstitutingInStream.h ++++ b/common/rdr/SubstitutingInStream.h +@@ -45,9 +45,9 @@ namespace rdr { + delete [] subst; + } + +- int pos() { return underlying->pos(); } ++ size_t pos() { return underlying->pos(); } + +- virtual int overrun(int itemSize, int nItems, bool wait=true) { ++ virtual size_t overrun(size_t itemSize, size_t nItems, bool wait=true) { + if (itemSize != 1) + throw new rdr::Exception("SubstitutingInStream: itemSize must be 1"); + diff --git a/SOURCES/tigervnc-CVE-2019-15695.patch b/SOURCES/tigervnc-CVE-2019-15695.patch new file mode 100644 index 0000000..44c380c --- /dev/null +++ b/SOURCES/tigervnc-CVE-2019-15695.patch @@ -0,0 +1,17 @@ +diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx +index a9d015d..896f4e5 100644 +--- a/common/rfb/PixelFormat.cxx ++++ b/common/rfb/PixelFormat.cxx +@@ -200,6 +200,12 @@ bool PixelFormat::is888(void) const + return false; + if (blueMax != 255) + return false; ++ if ((redShift & 0x7) != 0) ++ return false; ++ if ((greenShift & 0x7) != 0) ++ return false; ++ if ((blueShift & 0x7) != 0) ++ return false; + + return true; + } diff --git a/SOURCES/tigervnc-add-option-to-fallback-to-free-port.patch b/SOURCES/tigervnc-add-option-to-fallback-to-free-port.patch new file mode 100644 index 0000000..62cc8ce --- /dev/null +++ b/SOURCES/tigervnc-add-option-to-fallback-to-free-port.patch @@ -0,0 +1,36 @@ +diff --git a/unix/vncserver b/unix/vncserver +index 2ef436a..e032da5 100755 +--- a/unix/vncserver ++++ b/unix/vncserver +@@ -137,7 +137,7 @@ if ($fontPath eq "") { + # Check command line options + + &ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, +- "-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1); ++ "-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1,"-fallbacktofreeport",0); + + &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); + +@@ -184,7 +184,13 @@ if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { + $displayNumber = $1; + shift(@ARGV); + if (!&CheckDisplayNumber($displayNumber)) { +- die "A VNC server is already running as :$displayNumber\n"; ++ if ($opt{'-fallbacktofreeport'}) { ++ warn "A VNC server is already running as :$displayNumber\n"; ++ $displayNumber = &GetDisplayNumber(); ++ warn "Using port :$displayNumber as fallback\n"; ++ } else { ++ die "A VNC server is already running as :$displayNumber\n"; ++ } + } + } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) { + &Usage(); +@@ -688,6 +694,7 @@ sub Usage + " [-autokill]\n". + " [-noxstartup]\n". + " [-xstartup ]\n". ++ " [-fallbacktofreeport]\n". + " ...\n\n". + " $prog -kill \n\n". + " $prog -list\n\n"); diff --git a/SOURCES/tigervnc-add-write-protection-to-offsetpixelbuffer.patch b/SOURCES/tigervnc-add-write-protection-to-offsetpixelbuffer.patch new file mode 100644 index 0000000..39216f2 --- /dev/null +++ b/SOURCES/tigervnc-add-write-protection-to-offsetpixelbuffer.patch @@ -0,0 +1,51 @@ +From 9f615301aba1cc54a749950bf9462c5a85217bc4 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 10 Sep 2019 15:25:30 +0200 +Subject: [PATCH] Add write protection to OffsetPixelBuffer + +No one should every try to write to this buffer. Enforce that by +throwing an exception if any one tries to get a writeable pointer +to the data. +--- + common/rfb/EncodeManager.cxx | 6 ++++++ + common/rfb/EncodeManager.h | 3 +++ + 2 files changed, 9 insertions(+) + +diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx +index 1653cea..66ba432 100644 +--- a/common/rfb/EncodeManager.cxx ++++ b/common/rfb/EncodeManager.cxx +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -895,6 +896,11 @@ void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf, + setBuffer(width, height, (rdr::U8*)data_, stride_); + } + ++rdr::U8* EncodeManager::OffsetPixelBuffer::getBufferRW(const Rect& r, int* stride) ++{ ++ throw rfb::Exception("Invalid write attempt to OffsetPixelBuffer"); ++} ++ + // Preprocessor generated, optimised methods + + #define BPP 8 +diff --git a/common/rfb/EncodeManager.h b/common/rfb/EncodeManager.h +index 79db950..7d47420 100644 +--- a/common/rfb/EncodeManager.h ++++ b/common/rfb/EncodeManager.h +@@ -124,6 +124,9 @@ namespace rfb { + + void update(const PixelFormat& pf, int width, int height, + const rdr::U8* data_, int stride); ++ ++ private: ++ virtual rdr::U8* getBufferRW(const Rect& r, int* stride); + }; + + OffsetPixelBuffer offsetPixelBuffer; diff --git a/SOURCES/tigervnc-be-defensive-about-overflows-in-stream-objects.patch b/SOURCES/tigervnc-be-defensive-about-overflows-in-stream-objects.patch new file mode 100644 index 0000000..767b03d --- /dev/null +++ b/SOURCES/tigervnc-be-defensive-about-overflows-in-stream-objects.patch @@ -0,0 +1,355 @@ +From 75e6e0653a48baf474fd45d78b1da53e2f324642 Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 24 Sep 2019 09:41:07 +0200 +Subject: [PATCH] Be defensive about overflows in stream objects + +We use a lot of lengths given to us over the network, so be more +paranoid about them causing an overflow as otherwise an attacker +might trick us in to overwriting other memory. + +This primarily affects the client which often gets lengths from the +server, but there are also some scenarios where the server might +theoretically be vulnerable. + +Issue found by Pavel Cheremushkin from Kaspersky Lab. +--- + common/rdr/FdInStream.cxx | 8 +++++--- + common/rdr/FdOutStream.cxx | 7 ++++--- + common/rdr/FileInStream.cxx | 8 +++++--- + common/rdr/HexInStream.cxx | 8 +++++--- + common/rdr/HexOutStream.cxx | 6 ++++-- + common/rdr/InStream.h | 24 +++++++++++++----------- + common/rdr/MemOutStream.h | 4 ++++ + common/rdr/OutStream.h | 24 +++++++++++++----------- + common/rdr/RandomStream.cxx | 6 ++++-- + common/rdr/TLSInStream.cxx | 10 ++++++---- + common/rdr/TLSOutStream.cxx | 6 ++++-- + common/rdr/ZlibInStream.cxx | 6 ++++-- + common/rdr/ZlibOutStream.cxx | 6 ++++-- + 13 files changed, 75 insertions(+), 48 deletions(-) + +diff --git a/common/rdr/FdInStream.cxx b/common/rdr/FdInStream.cxx +index e99c108..bc944d1 100644 +--- a/common/rdr/FdInStream.cxx ++++ b/common/rdr/FdInStream.cxx +@@ -136,7 +136,7 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait) + ptr = start; + + size_t bytes_to_read; +- while (end < start + itemSize) { ++ while ((size_t)(end - start) < itemSize) { + bytes_to_read = start + bufSize - end; + if (!timing) { + // When not timing, we must be careful not to read too much +@@ -152,8 +152,10 @@ size_t FdInStream::overrun(size_t itemSize, size_t nItems, bool wait) + end += n; + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/FdOutStream.cxx b/common/rdr/FdOutStream.cxx +index 0900fd1..9d666e7 100644 +--- a/common/rdr/FdOutStream.cxx ++++ b/common/rdr/FdOutStream.cxx +@@ -148,9 +148,10 @@ size_t FdOutStream::overrun(size_t itemSize, size_t nItems) + } + } + +- // Can we fit all the items asked for? +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/FileInStream.cxx b/common/rdr/FileInStream.cxx +index 56830a0..42eaf11 100644 +--- a/common/rdr/FileInStream.cxx ++++ b/common/rdr/FileInStream.cxx +@@ -68,7 +68,7 @@ size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait) + ptr = b; + + +- while (end < b + itemSize) { ++ while ((size_t)(end - b) < itemSize) { + size_t n = fread((U8 *)end, b + sizeof(b) - end, 1, file); + if (n < 1) { + if (n < 0 || ferror(file)) +@@ -80,8 +80,10 @@ size_t FileInStream::overrun(size_t itemSize, size_t nItems, bool wait) + end += b + sizeof(b) - end; + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/HexInStream.cxx b/common/rdr/HexInStream.cxx +index 8f93988..a6bc92c 100644 +--- a/common/rdr/HexInStream.cxx ++++ b/common/rdr/HexInStream.cxx +@@ -91,7 +91,7 @@ size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) { + offset += ptr - start; + ptr = start; + +- while (end < ptr + itemSize) { ++ while ((size_t)(end - ptr) < itemSize) { + size_t n = in_stream.check(2, 1, wait); + if (n == 0) return 0; + const U8* iptr = in_stream.getptr(); +@@ -110,8 +110,10 @@ size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) { + end += length; + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/HexOutStream.cxx b/common/rdr/HexOutStream.cxx +index 7232514..eac2eff 100644 +--- a/common/rdr/HexOutStream.cxx ++++ b/common/rdr/HexOutStream.cxx +@@ -102,8 +102,10 @@ HexOutStream::overrun(size_t itemSize, size_t nItems) { + + writeBuffer(); + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/InStream.h b/common/rdr/InStream.h +index 14ecf09..f71a4d9 100644 +--- a/common/rdr/InStream.h ++++ b/common/rdr/InStream.h +@@ -43,12 +43,15 @@ namespace rdr { + + inline size_t check(size_t itemSize, size_t nItems=1, bool wait=true) + { +- if (ptr + itemSize * nItems > end) { +- if (ptr + itemSize > end) +- return overrun(itemSize, nItems, wait); ++ size_t nAvail; ++ ++ if (itemSize > (size_t)(end - ptr)) ++ return overrun(itemSize, nItems, wait); ++ ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + +- nItems = (end - ptr) / itemSize; +- } + return nItems; + } + +@@ -93,13 +96,12 @@ namespace rdr { + // readBytes() reads an exact number of bytes. + + void readBytes(void* data, size_t length) { +- U8* dataPtr = (U8*)data; +- U8* dataEnd = dataPtr + length; +- while (dataPtr < dataEnd) { +- size_t n = check(1, dataEnd - dataPtr); +- memcpy(dataPtr, ptr, n); ++ while (length > 0) { ++ size_t n = check(1, length); ++ memcpy(data, ptr, n); + ptr += n; +- dataPtr += n; ++ data = (U8*)data + n; ++ length -= n; + } + } + +diff --git a/common/rdr/MemOutStream.h b/common/rdr/MemOutStream.h +index 4a815b3..b56bac3 100644 +--- a/common/rdr/MemOutStream.h ++++ b/common/rdr/MemOutStream.h +@@ -23,6 +23,7 @@ + #ifndef __RDR_MEMOUTSTREAM_H__ + #define __RDR_MEMOUTSTREAM_H__ + ++#include + #include + + namespace rdr { +@@ -65,6 +66,9 @@ namespace rdr { + if (len < (size_t)(end - start) * 2) + len = (end - start) * 2; + ++ if (len < (size_t)(end - start)) ++ throw Exception("Overflow in MemOutStream::overrun()"); ++ + U8* newStart = new U8[len]; + memcpy(newStart, start, ptr - start); + ptr = newStart + (ptr - start); +diff --git a/common/rdr/OutStream.h b/common/rdr/OutStream.h +index 11aafd2..0f60ccc 100644 +--- a/common/rdr/OutStream.h ++++ b/common/rdr/OutStream.h +@@ -46,12 +46,15 @@ namespace rdr { + + inline size_t check(size_t itemSize, size_t nItems=1) + { +- if (ptr + itemSize * nItems > end) { +- if (ptr + itemSize > end) +- return overrun(itemSize, nItems); ++ size_t nAvail; ++ ++ if (itemSize > (size_t)(end - ptr)) ++ return overrun(itemSize, nItems); ++ ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + +- nItems = (end - ptr) / itemSize; +- } + return nItems; + } + +@@ -91,13 +94,12 @@ namespace rdr { + // writeBytes() writes an exact number of bytes. + + void writeBytes(const void* data, size_t length) { +- const U8* dataPtr = (const U8*)data; +- const U8* dataEnd = dataPtr + length; +- while (dataPtr < dataEnd) { +- size_t n = check(1, dataEnd - dataPtr); +- memcpy(ptr, dataPtr, n); ++ while (length > 0) { ++ size_t n = check(1, length); ++ memcpy(ptr, data, n); + ptr += n; +- dataPtr += n; ++ data = (U8*)data + n; ++ length -= n; + } + } + +diff --git a/common/rdr/RandomStream.cxx b/common/rdr/RandomStream.cxx +index 7681095..6c64ac5 100644 +--- a/common/rdr/RandomStream.cxx ++++ b/common/rdr/RandomStream.cxx +@@ -123,8 +123,10 @@ size_t RandomStream::overrun(size_t itemSize, size_t nItems, bool wait) { + *(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0)); + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx +index d0f9426..3e1172f 100644 +--- a/common/rdr/TLSInStream.cxx ++++ b/common/rdr/TLSInStream.cxx +@@ -43,7 +43,7 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size) + return -1; + } + +- if (in->getend() - in->getptr() < (ptrdiff_t)size) ++ if ((size_t)(in->getend() - in->getptr()) < size) + size = in->getend() - in->getptr(); + + in->readBytes(data, size); +@@ -92,15 +92,17 @@ size_t TLSInStream::overrun(size_t itemSize, size_t nItems, bool wait) + end -= ptr - start; + ptr = start; + +- while (end < start + itemSize) { ++ while ((size_t)(end - start) < itemSize) { + size_t n = readTLS((U8*) end, start + bufSize - end, wait); + if (!wait && n == 0) + return 0; + end += n; + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx +index 30c456f..7d7c3b5 100644 +--- a/common/rdr/TLSOutStream.cxx ++++ b/common/rdr/TLSOutStream.cxx +@@ -100,8 +100,10 @@ size_t TLSOutStream::overrun(size_t itemSize, size_t nItems) + + flush(); + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/ZlibInStream.cxx b/common/rdr/ZlibInStream.cxx +index e2f971c..9fcfaf6 100644 +--- a/common/rdr/ZlibInStream.cxx ++++ b/common/rdr/ZlibInStream.cxx +@@ -113,8 +113,10 @@ size_t ZlibInStream::overrun(size_t itemSize, size_t nItems, bool wait) + return 0; + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } +diff --git a/common/rdr/ZlibOutStream.cxx b/common/rdr/ZlibOutStream.cxx +index 4e7ffd6..5e158bf 100644 +--- a/common/rdr/ZlibOutStream.cxx ++++ b/common/rdr/ZlibOutStream.cxx +@@ -127,8 +127,10 @@ size_t ZlibOutStream::overrun(size_t itemSize, size_t nItems) + } + } + +- if (itemSize * nItems > (size_t)(end - ptr)) +- nItems = (end - ptr) / itemSize; ++ size_t nAvail; ++ nAvail = (end - ptr) / itemSize; ++ if (nAvail < nItems) ++ return nAvail; + + return nItems; + } diff --git a/SOURCES/tigervnc-encapsulate-pixelbuffer-internal-details.patch b/SOURCES/tigervnc-encapsulate-pixelbuffer-internal-details.patch new file mode 100644 index 0000000..07ef8f3 --- /dev/null +++ b/SOURCES/tigervnc-encapsulate-pixelbuffer-internal-details.patch @@ -0,0 +1,526 @@ +From 53f913a76196c7357d4858bfbf2c33caa9181bae Mon Sep 17 00:00:00 2001 +From: Pierre Ossman +Date: Tue, 10 Sep 2019 15:18:30 +0200 +Subject: [PATCH] Encapsulate PixelBuffer internal details + +Don't allow subclasses to just override dimensions or buffer details +directly and instead force them to go via methods. This allows us +to do sanity checks on the new values and catch bugs and attacks. +--- + common/rfb/Cursor.cxx | 3 +- + common/rfb/EncodeManager.cxx | 5 +- + common/rfb/PixelBuffer.cxx | 103 ++++++++++++++++---------- + common/rfb/PixelBuffer.h | 17 +++-- + unix/x0vncserver/XPixelBuffer.cxx | 9 +-- + unix/xserver/hw/vnc/XserverDesktop.cc | 24 +++--- + unix/xserver/hw/vnc/XserverDesktop.h | 2 +- + vncviewer/PlatformPixelBuffer.cxx | 9 +-- + win/rfb_win32/DIBSectionBuffer.cxx | 41 ++++------ + 9 files changed, 111 insertions(+), 102 deletions(-) + +diff --git a/common/rfb/Cursor.cxx b/common/rfb/Cursor.cxx +index 99df82d..7f3fc9a 100644 +--- a/common/rfb/Cursor.cxx ++++ b/common/rfb/Cursor.cxx +@@ -271,8 +271,7 @@ void RenderedCursor::update(PixelBuffer* framebuffer, + assert(cursor); + + format = framebuffer->getPF(); +- width_ = framebuffer->width(); +- height_ = framebuffer->height(); ++ setSize(framebuffer->width(), framebuffer->height()); + + rawOffset = pos.subtract(cursor->hotspot()); + clippedRect = Rect(0, 0, cursor->width(), cursor->height()) +diff --git a/common/rfb/EncodeManager.cxx b/common/rfb/EncodeManager.cxx +index 0cd5206..1653cea 100644 +--- a/common/rfb/EncodeManager.cxx ++++ b/common/rfb/EncodeManager.cxx +@@ -891,11 +891,8 @@ void EncodeManager::OffsetPixelBuffer::update(const PixelFormat& pf, + int stride_) + { + format = pf; +- width_ = width; +- height_ = height; + // Forced cast. We never write anything though, so it should be safe. +- data = (rdr::U8*)data_; +- stride = stride_; ++ setBuffer(width, height, (rdr::U8*)data_, stride_); + } + + // Preprocessor generated, optimised methods +diff --git a/common/rfb/PixelBuffer.cxx b/common/rfb/PixelBuffer.cxx +index 007b6c8..ad58324 100644 +--- a/common/rfb/PixelBuffer.cxx ++++ b/common/rfb/PixelBuffer.cxx +@@ -35,8 +35,14 @@ static LogWriter vlog("PixelBuffer"); + // -=- Generic pixel buffer class + + PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h) +- : format(pf), width_(w), height_(h) {} +-PixelBuffer::PixelBuffer() : width_(0), height_(0) {} ++ : format(pf), width_(0), height_(0) ++{ ++ setSize(w, h); ++} ++ ++PixelBuffer::PixelBuffer() : width_(0), height_(0) ++{ ++} + + PixelBuffer::~PixelBuffer() {} + +@@ -53,7 +59,7 @@ PixelBuffer::getImage(void* imageBuf, const Rect& r, int outStride) const + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d", + r.width(), r.height(), +- r.tl.x, r.tl.y, width_, height_); ++ r.tl.x, r.tl.y, width(), height()); + + data = getBuffer(r, &inStride); + +@@ -89,7 +95,7 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf, + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d", + r.width(), r.height(), +- r.tl.x, r.tl.y, width_, height_); ++ r.tl.x, r.tl.y, width(), height()); + + if (stride == 0) + stride = r.width(); +@@ -100,6 +106,12 @@ void PixelBuffer::getImage(const PixelFormat& pf, void* imageBuf, + stride, srcStride); + } + ++void PixelBuffer::setSize(int width, int height) ++{ ++ width_ = width; ++ height_ = height; ++} ++ + // -=- Modifiable generic pixel buffer class + + ModifiablePixelBuffer::ModifiablePixelBuffer(const PixelFormat& pf, +@@ -124,7 +136,7 @@ void ModifiablePixelBuffer::fillRect(const Rect& r, const void* pix) + + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d", +- r.width(), r.height(), r.tl.x, r.tl.y, width_, height_); ++ r.width(), r.height(), r.tl.x, r.tl.y, width(), height()); + + w = r.width(); + h = r.height(); +@@ -175,7 +187,7 @@ void ModifiablePixelBuffer::imageRect(const Rect& r, + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d", + r.width(), r.height(), +- r.tl.x, r.tl.y, width_, height_); ++ r.tl.x, r.tl.y, width(), height()); + + bytesPerPixel = getPF().bpp/8; + +@@ -213,13 +225,13 @@ void ModifiablePixelBuffer::copyRect(const Rect &rect, + if (!drect.enclosed_by(getRect())) + throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d", + drect.width(), drect.height(), +- drect.tl.x, drect.tl.y, width_, height_); ++ drect.tl.x, drect.tl.y, width(), height()); + + srect = drect.translate(move_by_delta.negate()); + if (!srect.enclosed_by(getRect())) + throw rfb::Exception("Source rect %dx%d at %d,%d exceeds framebuffer %dx%d", + srect.width(), srect.height(), +- srect.tl.x, srect.tl.y, width_, height_); ++ srect.tl.x, srect.tl.y, width(), height()); + + srcData = getBuffer(srect, &srcStride); + dstData = getBufferRW(drect, &dstStride); +@@ -272,7 +284,7 @@ void ModifiablePixelBuffer::imageRect(const PixelFormat& pf, const Rect &dest, + if (!dest.enclosed_by(getRect())) + throw rfb::Exception("Destination rect %dx%d at %d,%d exceeds framebuffer %dx%d", + dest.width(), dest.height(), +- dest.tl.x, dest.tl.y, width_, height_); ++ dest.tl.x, dest.tl.y, width(), height()); + + if (stride == 0) + stride = dest.width(); +@@ -301,7 +313,7 @@ rdr::U8* FullFramePixelBuffer::getBufferRW(const Rect& r, int* stride_) + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d", + r.width(), r.height(), +- r.tl.x, r.tl.y, width_, height_); ++ r.tl.x, r.tl.y, width(), height()); + + *stride_ = stride; + return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8]; +@@ -316,55 +328,69 @@ const rdr::U8* FullFramePixelBuffer::getBuffer(const Rect& r, int* stride_) cons + if (!r.enclosed_by(getRect())) + throw rfb::Exception("Pixel buffer request %dx%d at %d,%d exceeds framebuffer %dx%d", + r.width(), r.height(), +- r.tl.x, r.tl.y, width_, height_); ++ r.tl.x, r.tl.y, width(), height()); + + *stride_ = stride; + return &data[(r.tl.x + (r.tl.y * stride)) * format.bpp/8]; + } + ++void FullFramePixelBuffer::setBuffer(int width, int height, ++ rdr::U8* data_, int stride_) ++{ ++ ModifiablePixelBuffer::setSize(width, height); ++ stride = stride_; ++ data = data_; ++} ++ ++void FullFramePixelBuffer::setSize(int w, int h) ++{ ++ // setBuffer() should be used ++ throw rfb::Exception("Invalid call to FullFramePixelBuffer::setSize()"); ++} ++ + // -=- Managed pixel buffer class + // Automatically allocates enough space for the specified format & area + + ManagedPixelBuffer::ManagedPixelBuffer() +- : datasize(0) ++ : data_(NULL), datasize(0) + { +- checkDataSize(); + }; + + ManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h) +- : FullFramePixelBuffer(pf, w, h, NULL, w), datasize(0) ++ : FullFramePixelBuffer(pf, 0, 0, NULL, 0), data_(NULL), datasize(0) + { +- checkDataSize(); +-}; ++ setSize(w, h); ++} + +-ManagedPixelBuffer::~ManagedPixelBuffer() { +- if (data) delete [] data; +-}; ++ManagedPixelBuffer::~ManagedPixelBuffer() ++{ ++ if (data_) ++ delete [] data_; ++} + ++void ManagedPixelBuffer::setPF(const PixelFormat &pf) ++{ ++ format = pf; ++ setSize(width(), height()); ++} + +-void +-ManagedPixelBuffer::setPF(const PixelFormat &pf) { +- format = pf; checkDataSize(); +-}; +-void +-ManagedPixelBuffer::setSize(int w, int h) { +- width_ = w; height_ = h; stride = w; checkDataSize(); +-}; ++void ManagedPixelBuffer::setSize(int w, int h) ++{ ++ unsigned long new_datasize = w * h * (format.bpp/8); + ++ new_datasize = w * h * (format.bpp/8); + +-inline void +-ManagedPixelBuffer::checkDataSize() { +- unsigned long new_datasize = width_ * height_ * (format.bpp/8); + if (datasize < new_datasize) { +- if (data) { +- delete [] data; +- datasize = 0; data = 0; ++ if (data_) { ++ delete [] data_; ++ data_ = NULL; ++ datasize = 0; + } + if (new_datasize) { +- data = new U8[new_datasize]; +- if (!data) +- throw Exception("rfb::ManagedPixelBuffer unable to allocate buffer"); ++ data_ = new U8[new_datasize]; + datasize = new_datasize; + } + } +-}; ++ ++ setBuffer(w, h, data_, w); ++} +diff --git a/common/rfb/PixelBuffer.h b/common/rfb/PixelBuffer.h +index 75caa63..518c692 100644 +--- a/common/rfb/PixelBuffer.h ++++ b/common/rfb/PixelBuffer.h +@@ -89,7 +89,12 @@ namespace rfb { + + protected: + PixelBuffer(); ++ virtual void setSize(int width, int height); ++ ++ protected: + PixelFormat format; ++ ++ private: + int width_, height_; + }; + +@@ -153,7 +158,12 @@ namespace rfb { + + protected: + FullFramePixelBuffer(); ++ virtual void setBuffer(int width, int height, rdr::U8* data, int stride); + ++ private: ++ virtual void setSize(int w, int h); ++ ++ private: + rdr::U8* data; + int stride; + }; +@@ -171,12 +181,9 @@ namespace rfb { + virtual void setPF(const PixelFormat &pf); + virtual void setSize(int w, int h); + +- // Return the total number of bytes of pixel data in the buffer +- int dataLen() const { return width_ * height_ * (format.bpp/8); } +- +- protected: ++ private: ++ rdr::U8* data_; // Mirrors FullFramePixelBuffer::data + unsigned long datasize; +- void checkDataSize(); + }; + + }; +diff --git a/unix/x0vncserver/XPixelBuffer.cxx b/unix/x0vncserver/XPixelBuffer.cxx +index f464182..6f0effe 100644 +--- a/unix/x0vncserver/XPixelBuffer.cxx ++++ b/unix/x0vncserver/XPixelBuffer.cxx +@@ -50,13 +50,8 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, + ffs(m_image->xim->blue_mask) - 1); + + // Set up the remaining data of the parent class. +- width_ = rect.width(); +- height_ = rect.height(); +- data = (rdr::U8 *)m_image->xim->data; +- +- // Calculate the distance in pixels between two subsequent scan +- // lines of the framebuffer. This may differ from image width. +- stride = m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel; ++ setBuffer(rect.width(), rect.height(), (rdr::U8 *)m_image->xim->data, ++ m_image->xim->bytes_per_line * 8 / m_image->xim->bits_per_pixel); + + // Get initial screen image from the X display. + m_image->get(DefaultRootWindow(m_dpy), m_offsetLeft, m_offsetTop); +diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc +index 4836782..7daa69b 100644 +--- a/unix/xserver/hw/vnc/XserverDesktop.cc ++++ b/unix/xserver/hw/vnc/XserverDesktop.cc +@@ -101,7 +101,7 @@ XserverDesktop::XserverDesktop(int screenIndex_, + : screenIndex(screenIndex_), + server(0), httpServer(0), + listeners(listeners_), httpListeners(httpListeners_), +- directFbptr(true), ++ shadowFramebuffer(NULL), + queryConnectId(0) + { + format = pf; +@@ -138,8 +138,8 @@ XserverDesktop::~XserverDesktop() + delete httpListeners.back(); + httpListeners.pop_back(); + } +- if (!directFbptr) +- delete [] data; ++ if (shadowFramebuffer) ++ delete [] shadowFramebuffer; + delete httpServer; + delete server; + } +@@ -158,22 +158,18 @@ void XserverDesktop::setFramebuffer(int w, int h, void* fbptr, int stride_) + { + ScreenSet layout; + +- width_ = w; +- height_ = h; +- +- if (!directFbptr) { +- delete [] data; +- directFbptr = true; ++ if (shadowFramebuffer) { ++ delete [] shadowFramebuffer; ++ shadowFramebuffer = NULL; + } + + if (!fbptr) { +- fbptr = new rdr::U8[w * h * (format.bpp/8)]; ++ shadowFramebuffer = new rdr::U8[w * h * (format.bpp/8)]; ++ fbptr = shadowFramebuffer; + stride_ = w; +- directFbptr = false; + } + +- data = (rdr::U8*)fbptr; +- stride = stride_; ++ setBuffer(w, h, (rdr::U8*)fbptr, stride_); + + layout = computeScreenLayout(); + +@@ -749,7 +745,7 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, + + void XserverDesktop::grabRegion(const rfb::Region& region) + { +- if (directFbptr) ++ if (shadowFramebuffer == NULL) + return; + + std::vector rects; +diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h +index c766c26..22114a0 100644 +--- a/unix/xserver/hw/vnc/XserverDesktop.h ++++ b/unix/xserver/hw/vnc/XserverDesktop.h +@@ -121,7 +121,7 @@ private: + rfb::HTTPServer* httpServer; + std::list listeners; + std::list httpListeners; +- bool directFbptr; ++ rdr::U8* shadowFramebuffer; + + uint32_t queryConnectId; + network::Socket* queryConnectSocket; +diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx +index 22e4f72..2b934c5 100644 +--- a/vncviewer/PlatformPixelBuffer.cxx ++++ b/vncviewer/PlatformPixelBuffer.cxx +@@ -36,7 +36,7 @@ static rfb::LogWriter vlog("PlatformPixelBuffer"); + PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) : + FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true, + 255, 255, 255, 16, 8, 0), +- width, height, 0, stride), ++ 0, 0, NULL, 0), + Surface(width, height) + #if !defined(WIN32) && !defined(__APPLE__) + , shminfo(NULL), xim(NULL) +@@ -65,11 +65,10 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) : + vlog.debug("Using standard XImage"); + } + +- data = (rdr::U8*)xim->data; +- stride = xim->bytes_per_line / (getPF().bpp/8); ++ setBuffer(width, height, (rdr::U8*)xim->data, ++ xim->bytes_per_line / (getPF().bpp/8)); + #else +- FullFramePixelBuffer::data = (rdr::U8*)Surface::data; +- stride = width; ++ setBuffer(width, height, (rdr::U8*)Surface::data, width); + #endif + } + +diff --git a/win/rfb_win32/DIBSectionBuffer.cxx b/win/rfb_win32/DIBSectionBuffer.cxx +index e2b0d64..e00cf23 100644 +--- a/win/rfb_win32/DIBSectionBuffer.cxx ++++ b/win/rfb_win32/DIBSectionBuffer.cxx +@@ -52,39 +52,28 @@ void DIBSectionBuffer::setPF(const PixelFormat& pf) { + if (!pf.trueColour) + throw rfb::Exception("palette format not supported"); + format = pf; +- recreateBuffer(); ++ setSize(width(), height()); + } + +-void DIBSectionBuffer::setSize(int w, int h) { +- if (width_ == w && height_ == h) { +- vlog.debug("size unchanged by setSize()"); +- return; +- } +- width_ = w; +- height_ = h; +- recreateBuffer(); +-} +- +- + inline void initMaxAndShift(DWORD mask, int* max, int* shift) { + for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1; + (*max) = (rdr::U16)mask; + } + +-void DIBSectionBuffer::recreateBuffer() { ++void DIBSectionBuffer::setSize(int w, int h) { + HBITMAP new_bitmap = 0; + rdr::U8* new_data = 0; + +- if (width_ && height_ && (format.depth != 0)) { ++ if (w && h && (format.depth != 0)) { + BitmapInfo bi; + memset(&bi, 0, sizeof(bi)); + UINT iUsage = DIB_RGB_COLORS; + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biBitCount = format.bpp; +- bi.bmiHeader.biSizeImage = (format.bpp / 8) * width_ * height_; ++ bi.bmiHeader.biSizeImage = (format.bpp / 8) * w * h; + bi.bmiHeader.biPlanes = 1; +- bi.bmiHeader.biWidth = width_; +- bi.bmiHeader.biHeight = -height_; ++ bi.bmiHeader.biWidth = w; ++ bi.bmiHeader.biHeight = -h; + bi.bmiHeader.biCompression = (format.bpp > 8) ? BI_BITFIELDS : BI_RGB; + bi.mask.red = format.pixelFromRGB((rdr::U16)~0, 0, 0); + bi.mask.green = format.pixelFromRGB(0, (rdr::U16)~0, 0); +@@ -115,12 +104,12 @@ void DIBSectionBuffer::recreateBuffer() { + if (device) { + BitmapDC src_dev(device, bitmap); + BitmapDC dest_dev(device, new_bitmap); +- BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY); ++ BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY); + } else { + WindowDC wndDC(window); + BitmapDC src_dev(wndDC, bitmap); + BitmapDC dest_dev(wndDC, new_bitmap); +- BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY); ++ BitBlt(dest_dev, 0, 0, w, h, src_dev, 0, 0, SRCCOPY); + } + } + +@@ -128,17 +117,17 @@ void DIBSectionBuffer::recreateBuffer() { + // Delete the old bitmap + DeleteObject(bitmap); + bitmap = 0; +- data = 0; ++ setBuffer(0, 0, NULL, 0); + } + + if (new_bitmap) { + int bpp, depth; + int redMax, greenMax, blueMax; + int redShift, greenShift, blueShift; ++ int new_stride; + + // Set up the new bitmap + bitmap = new_bitmap; +- data = new_data; + + // Determine the *actual* DIBSection format + DIBSECTION ds; +@@ -147,14 +136,16 @@ void DIBSectionBuffer::recreateBuffer() { + + // Correct the "stride" of the DIB + // *** This code DWORD aligns each row - is that right??? +- stride = width_; +- int bytesPerRow = stride * format.bpp/8; ++ new_stride = w; ++ int bytesPerRow = new_stride * format.bpp/8; + if (bytesPerRow % 4) { + bytesPerRow += 4 - (bytesPerRow % 4); +- stride = (bytesPerRow * 8) / format.bpp; +- vlog.info("adjusting DIB stride: %d to %d", width_, stride); ++ new_stride = (bytesPerRow * 8) / format.bpp; ++ vlog.info("adjusting DIB stride: %d to %d", w, new_stride); + } + ++ setBuffer(w, h, new_data, new_stride); ++ + // Calculate the PixelFormat for the DIB + bpp = depth = ds.dsBm.bmBitsPixel; + diff --git a/SOURCES/tigervnc-pixelformat-sanity-checks.patch b/SOURCES/tigervnc-pixelformat-sanity-checks.patch new file mode 100644 index 0000000..9801a5c --- /dev/null +++ b/SOURCES/tigervnc-pixelformat-sanity-checks.patch @@ -0,0 +1,32 @@ +diff --git a/common/rfb/PixelFormat.cxx b/common/rfb/PixelFormat.cxx +index 76051dc..a9d015d 100644 +--- a/common/rfb/PixelFormat.cxx ++++ b/common/rfb/PixelFormat.cxx +@@ -75,7 +75,8 @@ PixelFormat::PixelFormat(int b, int d, bool e, bool t, + redMax(rm), greenMax(gm), blueMax(bm), + redShift(rs), greenShift(gs), blueShift(bs) + { +- assert(isSane()); ++ if (!isSane()) ++ throw Exception("invalid pixel format"); + + updateState(); + } +@@ -672,8 +673,16 @@ bool PixelFormat::isSane(void) + return false; + + totalBits = bits(redMax) + bits(greenMax) + bits(blueMax); +- if (totalBits > bpp) ++ if (totalBits > depth) ++ return false; ++ ++ if ((bits(redMax) + redShift) > bpp) ++ return false; ++ if ((bits(greenMax) + greenShift) > bpp) + return false; ++ if ((bits(blueMax) + blueShift) > bpp) ++ return false; ++ + + if (((redMax << redShift) & (greenMax << greenShift)) != 0) + return false; diff --git a/SOURCES/tigervnc-provide-correct-dimensions-for-xshm-setup.patch b/SOURCES/tigervnc-provide-correct-dimensions-for-xshm-setup.patch new file mode 100644 index 0000000..c4258a9 --- /dev/null +++ b/SOURCES/tigervnc-provide-correct-dimensions-for-xshm-setup.patch @@ -0,0 +1,44 @@ +diff --git a/vncviewer/PlatformPixelBuffer.cxx b/vncviewer/PlatformPixelBuffer.cxx +index 2b934c5..3d47163 100644 +--- a/vncviewer/PlatformPixelBuffer.cxx ++++ b/vncviewer/PlatformPixelBuffer.cxx +@@ -43,7 +43,7 @@ PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) : + #endif + { + #if !defined(WIN32) && !defined(__APPLE__) +- if (!setupShm()) { ++ if (!setupShm(width, height)) { + xim = XCreateImage(fl_display, CopyFromParent, 32, + ZPixmap, 0, 0, width, height, 32, 0); + if (!xim) +@@ -139,7 +139,7 @@ static int XShmAttachErrorHandler(Display *dpy, XErrorEvent *error) + return 0; + } + +-bool PlatformPixelBuffer::setupShm() ++bool PlatformPixelBuffer::setupShm(int width, int height) + { + int major, minor; + Bool pixmaps; +@@ -156,7 +156,7 @@ bool PlatformPixelBuffer::setupShm() + shminfo = new XShmSegmentInfo; + + xim = XShmCreateImage(fl_display, CopyFromParent, 32, +- ZPixmap, 0, shminfo, width(), height()); ++ ZPixmap, 0, shminfo, width, height); + if (!xim) + goto free_shminfo; + +diff --git a/vncviewer/PlatformPixelBuffer.h b/vncviewer/PlatformPixelBuffer.h +index f9038cd..ec439f6 100644 +--- a/vncviewer/PlatformPixelBuffer.h ++++ b/vncviewer/PlatformPixelBuffer.h +@@ -53,7 +53,7 @@ protected: + + #if !defined(WIN32) && !defined(__APPLE__) + protected: +- bool setupShm(); ++ bool setupShm(int width, int height); + + protected: + XShmSegmentInfo *shminfo; diff --git a/SPECS/tigervnc.spec b/SPECS/tigervnc.spec index cc6de4a..34a3e48 100644 --- a/SPECS/tigervnc.spec +++ b/SPECS/tigervnc.spec @@ -1,6 +1,6 @@ Name: tigervnc Version: 1.8.0 -Release: 19%{?dist} +Release: 21%{?dist} Summary: A TigerVNC remote display system Group: User Interface/Desktops @@ -53,7 +53,7 @@ Patch3: tigervnc-manpages.patch Patch4: tigervnc-cursor.patch Patch6: tigervnc-xstartup.patch Patch7: tigervnc-1.3.1-CVE-2014-8240.patch -Patch8: tigervnc-1.3.1-do-not-die-when-port-is-already-taken.patch +Patch8: tigervnc-add-option-to-fallback-to-free-port.patch Patch9: tigervnc-let-user-know-about-not-using-view-only-password.patch Patch10: tigervnc-working-tls-on-fips-systems.patch Patch11: tigervnc-broken-scrolling.patch @@ -64,12 +64,24 @@ Patch15: tigervnc-use-current-server-time-for-ungrab.patch Patch16: tigervnc-fix-rendering-on-big-endian-systems.patch Patch17: tigervnc-xvnc-update-manpage.patch Patch18: tigervnc-release-pointer-grab-when-cursor-leaves-window.patch +Patch19: tigervnc-provide-correct-dimensions-for-xshm-setup.patch # This is tigervnc-%{version}/unix/xserver116.patch rebased on the latest xorg Patch100: tigervnc-xserver120.patch # 1326867 - [RHEL7.3] GLX applications in an Xvnc session fails to start Patch101: 0001-rpath-hack.patch +# Security fixes +Patch200: tigervnc-CVE-2019-15691.patch +Patch201: tigervnc-encapsulate-pixelbuffer-internal-details.patch +Patch202: tigervnc-CVE-2019-15692.patch +Patch203: tigervnc-add-write-protection-to-offsetpixelbuffer.patch +Patch204: tigervnc-CVE-2019-15693.patch +Patch205: tigervnc-pixelformat-sanity-checks.patch +Patch206: tigervnc-CVE-2019-15694.patch +Patch207: tigervnc-be-defensive-about-overflows-in-stream-objects.patch +Patch208: tigervnc-CVE-2019-15695.patch + %description Virtual Network Computing (VNC) is a remote display system which allows you to view a computing 'desktop' environment not only on the @@ -189,7 +201,8 @@ popd %patch7 -p1 -b .tigervnc-1.3.1-CVE-2014-8240 # Bug 1322155 - Xorg socket conflict for VNC port 5901 -%patch8 -p1 -b .do-not-die-when-port-is-already-taken +# Bug 1791996 - TigerVNC should not arbitrarily start on unspecified ports +%patch8 -p1 -b .add-option-to-fallback-to-free-port # Bug 1447555 - view-only accepts enter, unclear whether default password is generated or not %patch9 -p1 -b .let-user-know-about-not-using-view-only-password @@ -214,6 +227,19 @@ popd %patch18 -p1 -b .release-pointer-grab-when-cursor-leaves-window +# Security fixes +%patch200 -p1 -b .CVE-2019-15691 +%patch201 -p1 -b .encapsulate-pixelbuffer-internal-details +%patch202 -p1 -b .CVE-2019-15692 +%patch203 -p1 -b .add-write-protection-to-offsetpixelbuffer +%patch204 -p1 -b .CVE-2019-15693 +%patch205 -p1 -b .pixelformat-sanity-checks +%patch206 -p1 -b .CVE-2019-15694 +%patch207 -p1 -b .be-defensive-about-overflows-in-stream-objects +%patch208 -p1 -b .CVE-2019-15695 + +%patch19 -p1 -b .provide-correct-dimensions-for-xshm-setup + %build %ifarch sparcv9 sparc64 s390 s390x export CFLAGS="$RPM_OPT_FLAGS -fPIC" @@ -383,6 +409,29 @@ fi %{_datadir}/icons/hicolor/*/apps/* %changelog +* Wed Apr 22 2020 Jan Grulich - 1.8.0-21 +- Add upstream patch needed because of previous security fixes + Resolves: bz#1826822 + +* Fri Feb 21 2020 Jan Grulich - 1.8.0-20 +- Fix stack buffer overflow in CMsgReader::readSetCursor + Resolves: bz#1791773 + +- Fix heap buffer overflow in DecodeManager::decodeRect + Resolves: bz#1791768 + +- Fix heap buffer overflow in TightDecoder::FilterGradient + Resolves: bz#1791763 + +- Fix heap-based buffer overflow triggered from CopyRectDecoder + Resolves: bz#1791747 + +- Fix stack use-after-return due to incorrect usage of stack memory in ZRLEDecoder + Resolves: bz#1791759 + +- Add option to fallback to empty port when the specified one is taken + Resolves: bz#1791996 + * Thu Oct 10 2019 Jan Grulich - 1.8.0-19 - Use vncserver wrapper script to workaround systemd issues Resolves: bz#1747191