summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/rfb/CMsgReader.cxx6
-rw-r--r--common/rfb/CMsgWriter.cxx3
-rw-r--r--common/rfb/SMsgReader.cxx6
-rw-r--r--common/rfb/SMsgWriter.cxx3
-rw-r--r--common/rfb/VNCServerST.cxx2
-rw-r--r--common/rfb/util.cxx56
-rw-r--r--common/rfb/util.h4
-rw-r--r--unix/xserver/hw/vnc/RFBGlue.cc16
-rw-r--r--unix/xserver/hw/vnc/RFBGlue.h5
-rw-r--r--unix/xserver/hw/vnc/vncSelection.c22
-rw-r--r--vncviewer/Viewport.cxx16
-rw-r--r--win/rfb_win32/Clipboard.cxx16
12 files changed, 123 insertions, 32 deletions
diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx
index 2b5b9fbf..a928eb15 100644
--- a/common/rfb/CMsgReader.cxx
+++ b/common/rfb/CMsgReader.cxx
@@ -157,10 +157,10 @@ void CMsgReader::readServerCutText()
vlog.error("cut text too long (%d bytes) - ignoring",len);
return;
}
- CharArray ca(len+1);
- ca.buf[len] = 0;
+ CharArray ca(len);
is->readBytes(ca.buf, len);
- handler->serverCutText(ca.buf, len);
+ CharArray filtered(convertLF(ca.buf, len));
+ handler->serverCutText(filtered.buf, strlen(filtered.buf));
}
void CMsgReader::readFence()
diff --git a/common/rfb/CMsgWriter.cxx b/common/rfb/CMsgWriter.cxx
index d357c976..fed0bd27 100644
--- a/common/rfb/CMsgWriter.cxx
+++ b/common/rfb/CMsgWriter.cxx
@@ -181,6 +181,9 @@ void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask)
void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
{
+ if (memchr(str, '\r', len) != NULL)
+ throw Exception("Invalid carriage return in clipboard data");
+
startMsg(msgTypeClientCutText);
os->pad(3);
os->writeU32(len);
diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx
index 200350c1..0c0e8b26 100644
--- a/common/rfb/SMsgReader.cxx
+++ b/common/rfb/SMsgReader.cxx
@@ -212,10 +212,10 @@ void SMsgReader::readClientCutText()
vlog.error("Cut text too long (%d bytes) - ignoring", len);
return;
}
- CharArray ca(len+1);
- ca.buf[len] = 0;
+ CharArray ca(len);
is->readBytes(ca.buf, len);
- handler->clientCutText(ca.buf, len);
+ CharArray filtered(convertLF(ca.buf, len));
+ handler->clientCutText(filtered.buf, strlen(filtered.buf));
}
void SMsgReader::readQEMUMessage()
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index 6a2c2ba0..f0748ff2 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -80,6 +80,9 @@ void SMsgWriter::writeBell()
void SMsgWriter::writeServerCutText(const char* str, int len)
{
+ if (memchr(str, '\r', len) != NULL)
+ throw Exception("Invalid carriage return in clipboard data");
+
startMsg(msgTypeServerCutText);
os->pad(3);
os->writeU32(len);
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
index c95c14f0..7820aef5 100644
--- a/common/rfb/VNCServerST.cxx
+++ b/common/rfb/VNCServerST.cxx
@@ -342,6 +342,8 @@ void VNCServerST::bell()
void VNCServerST::serverCutText(const char* str, int len)
{
+ if (memchr(str, '\r', len) != NULL)
+ throw Exception("Invalid carriage return in clipboard data");
std::list<VNCSConnectionST*>::iterator ci, ci_next;
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {
ci_next = ci; ci_next++;
diff --git a/common/rfb/util.cxx b/common/rfb/util.cxx
index f52213b3..f43a9453 100644
--- a/common/rfb/util.cxx
+++ b/common/rfb/util.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -107,6 +108,61 @@ namespace rfb {
dest[src ? destlen-1 : 0] = 0;
}
+ char* convertLF(const char* src, size_t bytes)
+ {
+ char* buffer;
+ size_t sz;
+
+ char* out;
+ const char* in;
+ size_t in_len;
+
+ // Always include space for a NULL
+ sz = 1;
+
+ // Compute output size
+ in = src;
+ in_len = bytes;
+ while ((*in != '\0') && (in_len > 0)) {
+ if (*in != '\r') {
+ sz++;
+ in++;
+ in_len--;
+ continue;
+ }
+
+ if ((in_len == 0) || (*(in+1) != '\n'))
+ sz++;
+
+ in++;
+ in_len--;
+ }
+
+ // Alloc
+ buffer = new char[sz];
+ memset(buffer, 0, sz);
+
+ // And convert
+ out = buffer;
+ in = src;
+ in_len = bytes;
+ while ((*in != '\0') && (in_len > 0)) {
+ if (*in != '\r') {
+ *out++ = *in++;
+ in_len--;
+ continue;
+ }
+
+ if ((in_len == 0) || (*(in+1) != '\n'))
+ *out++ = '\n';
+
+ in++;
+ in_len--;
+ }
+
+ return buffer;
+ }
+
unsigned msBetween(const struct timeval *first,
const struct timeval *second)
{
diff --git a/common/rfb/util.h b/common/rfb/util.h
index 9e59bd37..de096692 100644
--- a/common/rfb/util.h
+++ b/common/rfb/util.h
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -83,6 +84,9 @@ namespace rfb {
// Copies src to dest, up to specified length-1, and guarantees termination
void strCopy(char* dest, const char* src, int destlen);
+ // Makes sure line endings are in a certain format
+
+ char* convertLF(const char* src, size_t bytes = (size_t)-1);
// HELPER functions for timeout handling
diff --git a/unix/xserver/hw/vnc/RFBGlue.cc b/unix/xserver/hw/vnc/RFBGlue.cc
index 160177bd..d9c456e8 100644
--- a/unix/xserver/hw/vnc/RFBGlue.cc
+++ b/unix/xserver/hw/vnc/RFBGlue.cc
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2015 Pierre Ossman for Cendio AB
+ * Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -210,3 +210,17 @@ int vncIsTCPPortUsed(int port)
}
return 0;
}
+
+char* vncConvertLF(const char* src, size_t bytes)
+{
+ try {
+ return convertLF(src, bytes);
+ } catch (...) {
+ return NULL;
+ }
+}
+
+void vncStrFree(char* str)
+{
+ strFree(str);
+}
diff --git a/unix/xserver/hw/vnc/RFBGlue.h b/unix/xserver/hw/vnc/RFBGlue.h
index a63afd07..8e70c680 100644
--- a/unix/xserver/hw/vnc/RFBGlue.h
+++ b/unix/xserver/hw/vnc/RFBGlue.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2015 Pierre Ossman for Cendio AB
+ * Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -49,6 +49,9 @@ void vncListParams(int width, int nameWidth);
int vncGetSocketPort(int fd);
int vncIsTCPPortUsed(int port);
+char* vncConvertLF(const char* src, size_t bytes);
+void vncStrFree(char* str);
+
#ifdef __cplusplus
}
#endif
diff --git a/unix/xserver/hw/vnc/vncSelection.c b/unix/xserver/hw/vnc/vncSelection.c
index 4f3538d4..5ddcaf00 100644
--- a/unix/xserver/hw/vnc/vncSelection.c
+++ b/unix/xserver/hw/vnc/vncSelection.c
@@ -1,4 +1,4 @@
-/* Copyright 2016 Pierre Ossman for Cendio AB
+/* Copyright 2016-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -415,13 +415,22 @@ static void vncHandleSelection(Atom selection, Atom target,
else if (vncHasAtom(xaUTF8_STRING, (const Atom*)prop->data, prop->size))
vncSelectionRequest(selection, xaUTF8_STRING);
} else if (target == xaSTRING) {
+ char* filtered;
+
if (prop->format != 8)
return;
if (prop->type != xaSTRING)
return;
- vncServerCutText(prop->data, prop->size);
+ filtered = vncConvertLF(prop->data, prop->size);
+ if (filtered == NULL)
+ return;
+
+ vncServerCutText(filtered, strlen(filtered));
+
+ vncStrFree(filtered);
} else if (target == xaUTF8_STRING) {
+ char *filtered;
unsigned char* buffer;
unsigned char* out;
size_t len;
@@ -470,9 +479,14 @@ static void vncHandleSelection(Atom selection, Atom target,
}
}
- vncServerCutText((const char*)buffer, len);
-
+ filtered = vncConvertLF(buffer, len);
free(buffer);
+ if (filtered == NULL)
+ return;
+
+ vncServerCutText(filtered, strlen(filtered));
+
+ vncStrFree(filtered);
}
}
diff --git a/vncviewer/Viewport.cxx b/vncviewer/Viewport.cxx
index 5df5c796..15a3ec42 100644
--- a/vncviewer/Viewport.cxx
+++ b/vncviewer/Viewport.cxx
@@ -1,5 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
- * Copyright 2011-2014 Pierre Ossman for Cendio AB
+ * Copyright 2011-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -549,7 +549,7 @@ void Viewport::resize(int x, int y, int w, int h)
int Viewport::handle(int event)
{
- char *buffer;
+ char *buffer, *filtered;
int ret;
int buttonMask, wheelMask;
DownMap::const_iterator iter;
@@ -564,22 +564,26 @@ int Viewport::handle(int event)
ret = fl_utf8toa(Fl::event_text(), Fl::event_length(), buffer,
Fl::event_length() + 1);
assert(ret < (Fl::event_length() + 1));
+ filtered = convertLF(buffer, ret);
+ delete [] buffer;
if (!hasFocus()) {
- pendingClientCutText = buffer;
+ pendingClientCutText = new char[strlen(filtered) + 1];
+ strcpy((char*)pendingClientCutText, filtered);
+ strFree(filtered);
return 1;
}
- vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(buffer));
+ vlog.debug("Sending clipboard data (%d bytes)", (int)strlen(filtered));
try {
- cc->writer()->writeClientCutText(buffer, ret);
+ cc->writer()->writeClientCutText(filtered, strlen(filtered));
} catch (rdr::Exception& e) {
vlog.error("%s", e.str());
exit_vncviewer(e.str());
}
- delete [] buffer;
+ strFree(filtered);
return 1;
diff --git a/win/rfb_win32/Clipboard.cxx b/win/rfb_win32/Clipboard.cxx
index 0e290623..fca6c1df 100644
--- a/win/rfb_win32/Clipboard.cxx
+++ b/win/rfb_win32/Clipboard.cxx
@@ -1,4 +1,5 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
+ * Copyright 2012-2019 Pierre Ossman for Cendio AB
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -35,18 +36,6 @@ static LogWriter vlog("Clipboard");
//
char*
-dos2unix(const char* text) {
- int len = strlen(text)+1;
- char* unix = new char[strlen(text)+1];
- int i, j=0;
- for (i=0; i<len; i++) {
- if (text[i] != '\x0d')
- unix[j++] = text[i];
- }
- return unix;
-}
-
-char*
unix2dos(const char* text) {
int len = strlen(text)+1;
char* dos = new char[strlen(text)*2+1];
@@ -126,8 +115,7 @@ Clipboard::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {
if (!clipdata) {
notifier->notifyClipboardChanged(0, 0);
} else {
- CharArray unix_text;
- unix_text.buf = dos2unix(clipdata);
+ CharArray unix_text(convertLF(clipdata, strlen(clipdata)));
removeNonISOLatin1Chars(unix_text.buf);
notifier->notifyClipboardChanged(unix_text.buf, strlen(unix_text.buf));
}