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 <ossman@cendio.se>
+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 <ossman@cendio.se>
+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 <ossman@cendio.se>
+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 <ossman@cendio.se>
+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<b ? a : b;}
+ 
+-HexInStream::HexInStream(InStream& is, int bufSize_)
++HexInStream::HexInStream(InStream& is, size_t bufSize_)
+ : bufSize(bufSize_ ? bufSize_ : DEFAULT_BUF_LEN), offset(0), in_stream(is)
+ {
+   ptr = end = start = new U8[bufSize];
+@@ -50,8 +50,8 @@ bool HexInStream::readHexAndShift(char c, int* v) {
+   return true;
+ }
+ 
+-bool HexInStream::hexStrToBin(const char* s, char** data, int* length) {
+-  int l=strlen(s);
++bool HexInStream::hexStrToBin(const char* s, char** data, size_t* length) {
++  size_t l=strlen(s);
+   if ((l % 2) == 0) {
+     delete [] *data;
+     *data = 0; *length = 0;
+@@ -59,7 +59,7 @@ bool HexInStream::hexStrToBin(const char* s, char** data, int* length) {
+       return true;
+     *data = new char[l/2];
+     *length = l/2;
+-    for(int i=0;i<l;i+=2) {
++    for(size_t i=0;i<l;i+=2) {
+       int byte = 0;
+       if (!readHexAndShift(s[i], &byte) ||
+         !readHexAndShift(s[i+1], &byte))
+@@ -76,11 +76,11 @@ decodeError:
+ }
+ 
+ 
+-int HexInStream::pos() {
++size_t HexInStream::pos() {
+   return offset + ptr - start;
+ }
+ 
+-int HexInStream::overrun(int itemSize, int nItems, bool wait) {
++size_t HexInStream::overrun(size_t itemSize, size_t nItems, bool wait) {
+   if (itemSize > 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<length; i++) {
++    for (size_t i=0; i<length; i++) {
+       int v = 0;
+       readHexAndShift(iptr[i*2], &v);
+       readHexAndShift(iptr[i*2+1], &v);
+@@ -110,7 +110,7 @@ int HexInStream::overrun(int itemSize, int nItems, bool wait) {
+     end += length;
+   }
+ 
+-  if (itemSize * nItems > 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<b ? a : b;}
++static inline size_t min(size_t a, size_t b) {return a<b ? a : b;}
+ 
+-HexOutStream::HexOutStream(OutStream& os, int buflen)
++HexOutStream::HexOutStream(OutStream& os, size_t buflen)
+ : out_stream(os), offset(0), bufSize(buflen ? buflen : DEFAULT_BUF_LEN)
+ {
+   if (bufSize % 2)
+@@ -48,9 +48,9 @@ char HexOutStream::intToHex(int i) {
+     throw rdr::Exception("intToHex failed");
+ }
+ 
+-char* HexOutStream::binToHexStr(const char* data, int length) {
++char* HexOutStream::binToHexStr(const char* data, size_t length) {
+   char* buffer = new char[length*2+1];
+-  for (int i=0; i<length; i++) {
++  for (size_t i=0; i<length; i++) {
+     buffer[i*2] = intToHex((data[i] >> 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<length; i++) {
++    for (size_t i=0; i<length; i++) {
+       optr[i*2] = intToHex((pos[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<length; i++)
++    for (size_t i=0; i<length; i++)
+       *(U8*)end++ = (int) (256.0*rand()/(RAND_MAX+1.0));
+   }
+ 
+-  if (itemSize * nItems > 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<l ? plainPwd.buf[i] : 0;
+   deskey(d3desObfuscationKey, EN0);
+diff --git a/common/rfb/Password.h b/common/rfb/Password.h
+index e5196ee..712bc81 100644
+--- a/common/rfb/Password.h
++++ b/common/rfb/Password.h
+@@ -28,7 +28,7 @@ namespace rfb {
+   public:
+     PlainPasswd();
+     PlainPasswd(char* pwd);
+-    PlainPasswd(int len);
++    PlainPasswd(size_t len);
+     PlainPasswd(const ObfuscatedPasswd& obfPwd);
+     ~PlainPasswd();
+     void replaceBuf(char* b);
+@@ -37,10 +37,10 @@ namespace rfb {
+   class ObfuscatedPasswd : public CharArray {
+   public:
+     ObfuscatedPasswd();
+-    ObfuscatedPasswd(int l);
++    ObfuscatedPasswd(size_t l);
+     ObfuscatedPasswd(const PlainPasswd& plainPwd);
+     ~ObfuscatedPasswd();
+-    int length;
++    size_t length;
+   };
+ 
+ }
+diff --git a/common/rfb/util.h b/common/rfb/util.h
+index e9114c3..48c2ba6 100644
+--- a/common/rfb/util.h
++++ b/common/rfb/util.h
+@@ -45,7 +45,7 @@ namespace rfb {
+   public:
+     CharArray() : buf(0) {}
+     CharArray(char* str) : buf(str) {} // note: assumes ownership
+-    CharArray(int len) {
++    CharArray(size_t len) {
+       buf = new char[len];
+     }
+     ~CharArray() {
+diff --git a/win/rfb_win32/Registry.cxx b/win/rfb_win32/Registry.cxx
+index afbdd06..a81e822 100644
+--- a/win/rfb_win32/Registry.cxx
++++ b/win/rfb_win32/Registry.cxx
+@@ -146,7 +146,7 @@ void RegKey::setString(const TCHAR* valname, const TCHAR* value) const {
+   if (result != ERROR_SUCCESS) throw rdr::SystemException("setString", result);
+ }
+ 
+-void RegKey::setBinary(const TCHAR* valname, const void* value, int length) const {
++void RegKey::setBinary(const TCHAR* valname, const void* value, size_t length) const {
+   LONG result = RegSetValueEx(key, valname, 0, REG_BINARY, (const BYTE*)value, length);
+   if (result != ERROR_SUCCESS) throw rdr::SystemException("setBinary", result);
+ }
+@@ -169,12 +169,12 @@ TCHAR* RegKey::getString(const TCHAR* valname, const TCHAR* def) const {
+   }
+ }
+ 
+-void RegKey::getBinary(const TCHAR* valname, void** data, int* length) const {
++void RegKey::getBinary(const TCHAR* valname, void** data, size_t* length) const {
+   TCharArray hex(getRepresentation(valname));
+   if (!rdr::HexInStream::hexStrToBin(CStr(hex.buf), (char**)data, length))
+     throw rdr::Exception("getBinary failed");
+ }
+-void RegKey::getBinary(const TCHAR* valname, void** data, int* length, void* def, int deflen) const {
++void RegKey::getBinary(const TCHAR* valname, void** data, size_t* length, void* def, size_t deflen) const {
+   try {
+     getBinary(valname, data, length);
+   } catch(rdr::Exception) {
+diff --git a/win/rfb_win32/Registry.h b/win/rfb_win32/Registry.h
+index 68d535c..2bb1691 100644
+--- a/win/rfb_win32/Registry.h
++++ b/win/rfb_win32/Registry.h
+@@ -71,15 +71,15 @@ namespace rfb {
+ 
+       void setExpandString(const TCHAR* valname, const TCHAR* s) const;
+       void setString(const TCHAR* valname, const TCHAR* s) const;
+-      void setBinary(const TCHAR* valname, const void* data, int length) const;
++      void setBinary(const TCHAR* valname, const void* data, size_t length) const;
+       void setInt(const TCHAR* valname, int i) const;
+       void setBool(const TCHAR* valname, bool b) const;
+ 
+       TCHAR* getString(const TCHAR* valname) const;
+       TCHAR* getString(const TCHAR* valname, const TCHAR* def) const;
+ 
+-      void getBinary(const TCHAR* valname, void** data, int* length) const;
+-      void getBinary(const TCHAR* valname, void** data, int* length, void* def, int deflength) const;
++      void getBinary(const TCHAR* valname, void** data, size_t* length) const;
++      void getBinary(const TCHAR* valname, void** data, size_t* length, void* def, size_t deflength) const;
+ 
+       int getInt(const TCHAR* valname) const;
+       int getInt(const TCHAR* valname, int def) const;
+diff --git a/tests/encperf.cxx b/tests/encperf.cxx
+index 7b9ff81..f10dd6e 100644
+--- a/tests/encperf.cxx
++++ b/tests/encperf.cxx
+@@ -71,11 +71,11 @@ class DummyOutStream : public rdr::OutStream {
+ public:
+   DummyOutStream();
+ 
+-  virtual int length();
++  virtual size_t length();
+   virtual void flush();
+ 
+ private:
+-  virtual int overrun(int itemSize, int nItems);
++  virtual size_t overrun(size_t itemSize, size_t nItems);
+ 
+   int offset;
+   rdr::U8 buf[131072];
+@@ -141,7 +141,7 @@ DummyOutStream::DummyOutStream()
+   end = buf + sizeof(buf);
+ }
+ 
+-int DummyOutStream::length()
++size_t DummyOutStream::length()
+ {
+   flush();
+   return offset;
+@@ -153,10 +153,10 @@ void DummyOutStream::flush()
+   ptr = buf;
+ }
+ 
+-int DummyOutStream::overrun(int itemSize, int nItems)
++size_t DummyOutStream::overrun(size_t itemSize, size_t nItems)
+ {
+   flush();
+-  if (itemSize * nItems > 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 <file>]\n".
++	"                 [-fallbacktofreeport]\n".
+ 	"                 <Xvnc-options>...\n\n".
+ 	"       $prog -kill <X-display>\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 <ossman@cendio.se>
+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 <rfb/SMsgWriter.h>
+ #include <rfb/UpdateTracker.h>
+ #include <rfb/LogWriter.h>
++#include <rfb/Exception.h>
+ 
+ #include <rfb/RawEncoder.h>
+ #include <rfb/RREEncoder.h>
+@@ -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 <ossman@cendio.se>
+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 <rdr/Exception.h>
+ #include <rdr/OutStream.h>
+ 
+ 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 <ossman@cendio.se>
+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<rfb::Rect> 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<network::TcpListener*> listeners;
+   std::list<network::TcpListener*> 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/vncserver.service b/SOURCES/vncserver.service
index 5077e82..7b9cb2f 100644
--- a/SOURCES/vncserver.service
+++ b/SOURCES/vncserver.service
@@ -3,9 +3,7 @@
 # Quick HowTo:
 # 1. Copy this file to /etc/systemd/system/vncserver@.service
 # 2. Replace <USER> with the actual user name and edit vncserver
-#    parameters appropriately
-#    (ExecStart=/usr/sbin/runuser -l <USER> -c "/usr/bin/vncserver %i"
-#     PIDFile=/home/<USER>/.vnc/%H%i.pid)
+#    parameters in the wrapper script located in /usr/bin/vncserver_wrapper
 # 3. Run `systemctl daemon-reload`
 # 4. Run `systemctl enable vncserver@:<display>.service`
 #
@@ -36,12 +34,11 @@ Description=Remote desktop service (VNC)
 After=syslog.target network.target
 
 [Service]
-Type=forking
+Type=simple
 
 # Clean any existing files in /tmp/.X11-unix environment
 ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
-ExecStart=/usr/sbin/runuser -l <USER> -c "/usr/bin/vncserver %i"
-PIDFile=/home/<USER>/.vnc/%H%i.pid
+ExecStart=/usr/bin/vncserver_wrapper <USER> %i
 ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
 
 [Install]
diff --git a/SOURCES/vncserver_wrapper b/SOURCES/vncserver_wrapper
new file mode 100755
index 0000000..0c8f994
--- /dev/null
+++ b/SOURCES/vncserver_wrapper
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+USER="$1"
+INSTANCE="$2"
+
+die() {
+	echo "FATAL: ${@:-}" >&2
+	exit 2
+}
+
+cleanup() {
+	[ -n "$VNCPID" ] || return
+	if kill -0 $VNCPID 2>/dev/null; then
+		kill $VNCPID
+	fi
+}
+
+trap cleanup TERM INT HUP
+
+[ -n "$USER" -a -n "$INSTANCE" ] || die "Invalid usage!"
+
+/usr/sbin/runuser -l "$USER" -c "/usr/bin/vncserver ${INSTANCE}"
+[ $? -eq 0 ] || die "'runuser -l $USER' failed!"
+
+# Wait up to 5 seconds for vncserver to be up
+for tries in $(seq 1 50); do
+	[ -e "~$USER/.vnc/$(hostname)${INSTANCE}.pid" ] && break
+	sleep 0.1
+done
+
+eval HOME=~$USER
+
+VNCPID=$(cat "$HOME/.vnc/$(hostname)${INSTANCE}.pid" 2>/dev/null || true)
+[ -n "$VNCPID" ] || die "'vncserver ${INSTANCE}' failed to start after 5 seconds!"
+
+echo "'vncserver ${INSTANCE}' has PID $VNCPID, waiting until it exits ..."
+
+while kill -0 $VNCPID 2>/dev/null; do
+	sleep 5
+done
+
+echo "PID $VNCPID exited, exiting ..."
diff --git a/SPECS/tigervnc.spec b/SPECS/tigervnc.spec
index 37570cb..b69d861 100644
--- a/SPECS/tigervnc.spec
+++ b/SPECS/tigervnc.spec
@@ -1,6 +1,6 @@
 Name:           tigervnc
 Version:        1.8.0
-Release:        18%{?dist}
+Release:        20%{?dist}
 Summary:        A TigerVNC remote display system
 
 Group:          User Interface/Desktops
@@ -13,6 +13,7 @@ Source2:        vncserver.sysconfig
 Source3:        10-libvnc.conf
 Source4:        xvnc.service
 Source5:        xvnc.socket
+Source6:        vncserver_wrapper
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
 BuildRequires:  libX11-devel, automake, autoconf, libtool, gettext, gettext-autopoint
@@ -52,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
@@ -69,6 +70,17 @@ 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
@@ -188,7 +200,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
@@ -213,6 +226,17 @@ 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
+
 %build
 %ifarch sparcv9 sparc64 s390 s390x
 export CFLAGS="$RPM_OPT_FLAGS -fPIC"
@@ -272,6 +296,9 @@ install -m644 %{SOURCE4} %{buildroot}%{_unitdir}/xvnc@.service
 install -m644 %{SOURCE5} %{buildroot}%{_unitdir}/xvnc.socket
 rm -rf %{buildroot}%{_initrddir}
 
+# Install vncserver wrapper script
+install -m744 %{SOURCE6} %{buildroot}%{_bindir}/vncserver_wrapper
+
 mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
 install -m644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/vncservers
 
@@ -333,7 +360,9 @@ fi
 %systemd_preun xvnc.socket
 
 %postun server
-%systemd_postun
+%systemd_postun vncserver.service
+%systemd_postun xvnc.service
+%systemd_postun xvnc.socket
 
 %files -f %{name}.lang
 %doc README.txt
@@ -348,6 +377,7 @@ fi
 %{_unitdir}/xvnc.socket
 %{_bindir}/x0vncserver
 %{_bindir}/vncserver
+%{_bindir}/vncserver_wrapper
 %{_mandir}/man1/vncserver.1*
 %{_mandir}/man1/x0vncserver.1*
 
@@ -376,6 +406,29 @@ fi
 %{_datadir}/icons/hicolor/*/apps/*
 
 %changelog
+* Fri Feb 21 2020 Jan Grulich <jgrulich@redhat.com> - 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 <jgrulich@redhat.com> - 1.8.0-19
+- Use vncserver wrapper script to workaround systemd issues
+  Resolves: bz#1747191
+
 * Tue Aug 13 2019 Adam Jackson <ajax@redhat.com> - 1.8.0-18
 - Rebuild against newer X server to pick up backing store crash fixes
   Resolves: bz#1670342