e84ad30
qt-bugs@ issue : N154454
e84ad30
bugs.kde.org number : none
e84ad30
applied: no
e84ad30
author: Dirk Mueller <mueller@kde.org>
e84ad30
e84ad30
This patch makes the utf8 decoders in Qt reject overlong
e84ad30
sequences, like required.
e84ad30
e84ad30
--- src/codecs/qutfcodec.cpp
e84ad30
+++ src/codecs/qutfcodec.cpp
e84ad30
@@ -154,6 +154,7 @@
e84ad30
 
e84ad30
 class QUtf8Decoder : public QTextDecoder {
e84ad30
     uint uc;
e84ad30
+    uint min_uc;
e84ad30
     int need;
e84ad30
     bool headerDone;
e84ad30
 public:
e84ad30
@@ -167,8 +168,9 @@
e84ad30
 	result.setLength( len ); // worst case
e84ad30
 	QChar *qch = (QChar *)result.unicode();
e84ad30
 	uchar ch;
e84ad30
+        int error = -1;
e84ad30
 	for (int i=0; i
e84ad30
-	    ch = *chars++;
e84ad30
+	    ch = chars[i];
e84ad30
 	    if (need) {
e84ad30
 		if ( (ch&0xc0) == 0x80 ) {
e84ad30
 		    uc = (uc << 6) | (ch & 0x3f);
e84ad30
@@ -182,6 +184,8 @@
e84ad30
 			    *qch++ = QChar(high);
e84ad30
 			    *qch++ = QChar(low);
e84ad30
 			    headerDone = TRUE;
e84ad30
+			} else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
e84ad30
+                            *qch++ = QChar::replacement;
e84ad30
 			} else {
e84ad30
 			    if (headerDone || QChar(uc) != QChar::byteOrderMark)
e84ad30
 				*qch++ = uc;
e84ad30
@@ -190,6 +194,7 @@
e84ad30
 		    }
e84ad30
 		} else {
e84ad30
 		    // error
e84ad30
+                    i = error;
e84ad30
 		    *qch++ = QChar::replacement;
e84ad30
 		    need = 0;
e84ad30
 		}
e84ad30
@@ -200,12 +205,21 @@
e84ad30
 		} else if ((ch & 0xe0) == 0xc0) {
e84ad30
 		    uc = ch & 0x1f;
e84ad30
 		    need = 1;
e84ad30
+                    error = i;
e84ad30
+		    min_uc = 0x80;
e84ad30
 		} else if ((ch & 0xf0) == 0xe0) {
e84ad30
 		    uc = ch & 0x0f;
e84ad30
 		    need = 2;
e84ad30
+                    error = i;
e84ad30
+		    min_uc = 0x800;
e84ad30
 		} else if ((ch&0xf8) == 0xf0) {
e84ad30
 		    uc = ch & 0x07;
e84ad30
 		    need = 3;
e84ad30
+                    error = i;
e84ad30
+                    min_uc = 0x10000;
e84ad30
+                } else {
e84ad30
+                    // error
e84ad30
+                    *qch++ = QChar::replacement;
e84ad30
 		}
e84ad30
 	    }
e84ad30
 	}
e84ad30
--- src/tools/qstring.cpp
e84ad30
+++ src/tools/qstring.cpp
e84ad30
@@ -5805,6 +5805,7 @@
e84ad30
     result.setLength( len ); // worst case
e84ad30
     QChar *qch = (QChar *)result.unicode();
e84ad30
     uint uc = 0;
e84ad30
+    uint min_uc = 0;
e84ad30
     int need = 0;
e84ad30
     int error = -1;
e84ad30
     uchar ch;
e84ad30
@@ -5822,6 +5823,12 @@
e84ad30
 			unsigned short low = uc%0x400 + 0xdc00;
e84ad30
 			*qch++ = QChar(high);
e84ad30
 			*qch++ = QChar(low);
e84ad30
+		    } else if (uc < min_uc || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
e84ad30
+			// overlong seqence, UTF16 surrogate or BOM
e84ad30
+                        i = error;
e84ad30
+                        qch = addOne(qch, result);
e84ad30
+                        *qch++ = QChar(0xdbff);
e84ad30
+                        *qch++ = QChar(0xde00+((uchar)utf8[i]));
e84ad30
 		    } else {
e84ad30
 			*qch++ = uc;
e84ad30
 		    }
e84ad30
@@ -5844,14 +5851,17 @@
e84ad30
 		uc = ch & 0x1f;
e84ad30
 		need = 1;
e84ad30
 		error = i;
e84ad30
+		min_uc = 0x80;
e84ad30
 	    } else if ((ch & 0xf0) == 0xe0) {
e84ad30
 		uc = ch & 0x0f;
e84ad30
 		need = 2;
e84ad30
 		error = i;
e84ad30
+		min_uc = 0x800;
e84ad30
 	    } else if ((ch&0xf8) == 0xf0) {
e84ad30
 		uc = ch & 0x07;
e84ad30
 		need = 3;
e84ad30
 		error = i;
e84ad30
+		min_uc = 0x10000;
e84ad30
 	    } else {
e84ad30
 	        // Error
e84ad30
                 qch = addOne(qch, result);