mirror of
https://git.FreeBSD.org/ports.git
synced 2024-12-21 04:06:46 +00:00
Fix handling of overlong UTF8 sequences in Qt and kdelibs, which, unpatched,
introduces XSS vulnerabilities in Konqueror and potentially affect any Qt/KDE applications which deal with URLs or paths from untrusted locations. Security: CVE-2007-0242
This commit is contained in:
parent
200db6b63d
commit
bf4e60e8bf
Notes:
svn2git
2021-03-31 03:12:20 +00:00
svn path=/head/; revision=188834
@ -8,7 +8,7 @@
|
||||
|
||||
PORTNAME= corelib
|
||||
PORTVERSION= 4.2.3
|
||||
PORTREVISION= 0
|
||||
PORTREVISION= 1
|
||||
CATEGORIES?= devel
|
||||
MASTER_SITES= ${MASTER_SITE_QT}
|
||||
PKGNAMEPREFIX= qt4-
|
||||
@ -62,6 +62,7 @@ EXTRACT_AFTER_ARGS=| ${TAR} -xf - \
|
||||
--exclude '${DISTNAME}/tools/qtconfig' --exclude '${DISTNAME}/tools/qvfb'
|
||||
WRKSRC= ${WRKDIR}/${DISTNAME}/src/${PORTNAME}
|
||||
CONFIGURE_WRKSRC=${WRKSRC}/../../
|
||||
PATCH_WRKSRC=${WRKSRC}/../../
|
||||
|
||||
.include <bsd.port.pre.mk>
|
||||
|
||||
|
132
devel/qt4-corelib/files/patch-utf8-bug-qt4
Normal file
132
devel/qt4-corelib/files/patch-utf8-bug-qt4
Normal file
@ -0,0 +1,132 @@
|
||||
--- src/corelib/tools/qstring.cpp
|
||||
+++ src/corelib/tools/qstring.cpp
|
||||
@@ -3342,6 +3342,7 @@ QString QString::fromUtf8(const char *st
|
||||
result.resize(size); // worst case
|
||||
ushort *qch = result.d->data;
|
||||
uint uc = 0;
|
||||
+ uint min_uc = 0;
|
||||
int need = 0;
|
||||
int error = -1;
|
||||
uchar ch;
|
||||
@@ -3359,6 +3360,12 @@ QString QString::fromUtf8(const char *st
|
||||
ushort low = uc%0x400 + 0xdc00;
|
||||
*qch++ = high;
|
||||
*qch++ = low;
|
||||
+ } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
|
||||
+ // overlong seqence, UTF16 surrogate or BOM
|
||||
+ i = error;
|
||||
+ qch = addOne(qch, result);
|
||||
+ *qch++ = 0xdbff;
|
||||
+ *qch++ = 0xde00 + ((uchar)str[i]);
|
||||
} else {
|
||||
*qch++ = uc;
|
||||
}
|
||||
@@ -3381,14 +3388,17 @@ QString QString::fromUtf8(const char *st
|
||||
uc = ch & 0x1f;
|
||||
need = 1;
|
||||
error = i;
|
||||
+ min_uc = 0x80;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
uc = ch & 0x0f;
|
||||
need = 2;
|
||||
error = i;
|
||||
+ min_uc = 0x800;
|
||||
} else if ((ch&0xf8) == 0xf0) {
|
||||
uc = ch & 0x07;
|
||||
need = 3;
|
||||
error = i;
|
||||
+ min_uc = 0x10000;
|
||||
} else {
|
||||
// Error
|
||||
qch = addOne(qch, result);
|
||||
--- src/corelib/codecs/qutfcodec.cpp
|
||||
+++ src/corelib/codecs/qutfcodec.cpp
|
||||
@@ -117,15 +117,19 @@ QString QUtf8Codec::convertToUnicode(con
|
||||
bool headerdone = false;
|
||||
QChar replacement = QChar::ReplacementCharacter;
|
||||
int need = 0;
|
||||
+ int error = -1;
|
||||
uint uc = 0;
|
||||
+ uint min_uc = 0;
|
||||
if (state) {
|
||||
if (state->flags & IgnoreHeader)
|
||||
headerdone = true;
|
||||
if (state->flags & ConvertInvalidToNull)
|
||||
replacement = QChar::Null;
|
||||
need = state->remainingChars;
|
||||
- if (need)
|
||||
+ if (need) {
|
||||
uc = state->state_data[0];
|
||||
+ min_uc = state->state_data[1];
|
||||
+ }
|
||||
}
|
||||
if (!headerdone && len > 3
|
||||
&& (uchar)chars[0] == 0xef && (uchar)chars[1] == 0xbb && (uchar)chars[2] == 0xbf) {
|
||||
@@ -142,7 +146,7 @@ QString QUtf8Codec::convertToUnicode(con
|
||||
int invalid = 0;
|
||||
|
||||
for (int i=0; i<len; i++) {
|
||||
- ch = *chars++;
|
||||
+ ch = chars[i];
|
||||
if (need) {
|
||||
if ((ch&0xc0) == 0x80) {
|
||||
uc = (uc << 6) | (ch & 0x3f);
|
||||
@@ -153,14 +157,27 @@ QString QUtf8Codec::convertToUnicode(con
|
||||
uc -= 0x10000;
|
||||
unsigned short high = uc/0x400 + 0xd800;
|
||||
unsigned short low = uc%0x400 + 0xdc00;
|
||||
+
|
||||
+ // resize if necessary
|
||||
+ long where = qch - result.unicode();
|
||||
+ if (where + 2 >= result.size()) {
|
||||
+ result.resize(where + 2);
|
||||
+ qch = result.data() + where;
|
||||
+ }
|
||||
+
|
||||
*qch++ = QChar(high);
|
||||
*qch++ = QChar(low);
|
||||
+ } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
|
||||
+ // error
|
||||
+ *qch++ = QChar::ReplacementCharacter;
|
||||
+ ++invalid;
|
||||
} else {
|
||||
*qch++ = uc;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// error
|
||||
+ i = error;
|
||||
*qch++ = QChar::ReplacementCharacter;
|
||||
++invalid;
|
||||
need = 0;
|
||||
@@ -171,12 +188,22 @@ QString QUtf8Codec::convertToUnicode(con
|
||||
} else if ((ch & 0xe0) == 0xc0) {
|
||||
uc = ch & 0x1f;
|
||||
need = 1;
|
||||
+ error = i;
|
||||
+ min_uc = 0x80;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
uc = ch & 0x0f;
|
||||
need = 2;
|
||||
+ error = i;
|
||||
+ min_uc = 0x800;
|
||||
} else if ((ch&0xf8) == 0xf0) {
|
||||
uc = ch & 0x07;
|
||||
need = 3;
|
||||
+ error = i;
|
||||
+ min_uc = 0x10000;
|
||||
+ } else {
|
||||
+ // error
|
||||
+ *qch++ = QChar::ReplacementCharacter;
|
||||
+ ++invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,6 +214,7 @@ QString QUtf8Codec::convertToUnicode(con
|
||||
if (headerdone)
|
||||
state->flags |= IgnoreHeader;
|
||||
state->state_data[0] = need ? uc : 0;
|
||||
+ state->state_data[1] = need ? min_uc : 0;
|
||||
}
|
||||
return result;
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
|
||||
PORTNAME= qt
|
||||
PORTVERSION= 3.3.8
|
||||
PORTREVISION= 1
|
||||
CATEGORIES?= x11-toolkits ipv6
|
||||
MASTER_SITES= ${MASTER_SITE_QT}
|
||||
DISTNAME= qt-x11-free-${PORTVERSION}
|
||||
|
101
x11-toolkits/qt33/files/patch-utf8-bug-qt3
Normal file
101
x11-toolkits/qt33/files/patch-utf8-bug-qt3
Normal file
@ -0,0 +1,101 @@
|
||||
--- src/codecs/qutfcodec.cpp
|
||||
+++ src/codecs/qutfcodec.cpp
|
||||
@@ -154,6 +154,7 @@
|
||||
|
||||
class QUtf8Decoder : public QTextDecoder {
|
||||
uint uc;
|
||||
+ uint min_uc;
|
||||
int need;
|
||||
bool headerDone;
|
||||
public:
|
||||
@@ -167,8 +168,9 @@
|
||||
result.setLength( len ); // worst case
|
||||
QChar *qch = (QChar *)result.unicode();
|
||||
uchar ch;
|
||||
+ int error = -1;
|
||||
for (int i=0; i<len; i++) {
|
||||
- ch = *chars++;
|
||||
+ ch = chars[i];
|
||||
if (need) {
|
||||
if ( (ch&0xc0) == 0x80 ) {
|
||||
uc = (uc << 6) | (ch & 0x3f);
|
||||
@@ -182,6 +184,8 @@
|
||||
*qch++ = QChar(high);
|
||||
*qch++ = QChar(low);
|
||||
headerDone = TRUE;
|
||||
+ } else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
|
||||
+ *qch++ = QChar::replacement;
|
||||
} else {
|
||||
if (headerDone || QChar(uc) != QChar::byteOrderMark)
|
||||
*qch++ = uc;
|
||||
@@ -190,6 +194,7 @@
|
||||
}
|
||||
} else {
|
||||
// error
|
||||
+ i = error;
|
||||
*qch++ = QChar::replacement;
|
||||
need = 0;
|
||||
}
|
||||
@@ -200,12 +205,21 @@
|
||||
} else if ((ch & 0xe0) == 0xc0) {
|
||||
uc = ch & 0x1f;
|
||||
need = 1;
|
||||
+ error = i;
|
||||
+ min_uc = 0x80;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
uc = ch & 0x0f;
|
||||
need = 2;
|
||||
+ error = i;
|
||||
+ min_uc = 0x800;
|
||||
} else if ((ch&0xf8) == 0xf0) {
|
||||
uc = ch & 0x07;
|
||||
need = 3;
|
||||
+ error = i;
|
||||
+ min_uc = 0x10000;
|
||||
+ } else {
|
||||
+ // error
|
||||
+ *qch++ = QChar::replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
--- src/tools/qstring.cpp
|
||||
+++ src/tools/qstring.cpp
|
||||
@@ -5805,6 +5805,7 @@
|
||||
result.setLength( len ); // worst case
|
||||
QChar *qch = (QChar *)result.unicode();
|
||||
uint uc = 0;
|
||||
+ uint min_uc = 0;
|
||||
int need = 0;
|
||||
int error = -1;
|
||||
uchar ch;
|
||||
@@ -5822,6 +5823,12 @@
|
||||
unsigned short low = uc%0x400 + 0xdc00;
|
||||
*qch++ = QChar(high);
|
||||
*qch++ = QChar(low);
|
||||
+ } else if (uc < min_uc || (uc >= 0xd800 && uc <= 0xdfff) || (uc >= 0xfffe)) {
|
||||
+ // overlong seqence, UTF16 surrogate or BOM
|
||||
+ i = error;
|
||||
+ qch = addOne(qch, result);
|
||||
+ *qch++ = QChar(0xdbff);
|
||||
+ *qch++ = QChar(0xde00+((uchar)utf8[i]));
|
||||
} else {
|
||||
*qch++ = uc;
|
||||
}
|
||||
@@ -5844,14 +5851,17 @@
|
||||
uc = ch & 0x1f;
|
||||
need = 1;
|
||||
error = i;
|
||||
+ min_uc = 0x80;
|
||||
} else if ((ch & 0xf0) == 0xe0) {
|
||||
uc = ch & 0x0f;
|
||||
need = 2;
|
||||
error = i;
|
||||
+ min_uc = 0x800;
|
||||
} else if ((ch&0xf8) == 0xf0) {
|
||||
uc = ch & 0x07;
|
||||
need = 3;
|
||||
error = i;
|
||||
+ min_uc = 0x10000;
|
||||
} else {
|
||||
// Error
|
||||
qch = addOne(qch, result);
|
@ -8,7 +8,7 @@
|
||||
|
||||
PORTNAME= kdelibs
|
||||
PORTVERSION= ${KDE_VERSION}
|
||||
PORTREVISION= 1
|
||||
PORTREVISION= 2
|
||||
CATEGORIES= x11 kde ipv6
|
||||
MASTER_SITES= ${MASTER_SITE_KDE}
|
||||
MASTER_SITE_SUBDIR= stable/${PORTVERSION:S/.0//}/src
|
||||
|
38
x11/kdelibs3/files/patch-kdelibs-kjs
Normal file
38
x11/kdelibs3/files/patch-kdelibs-kjs
Normal file
@ -0,0 +1,38 @@
|
||||
------------------------------------------------------------------------
|
||||
r645387 | porten | 2007-03-22 15:01:13 +0100 (Thu, 22 Mar 2007) | 4 lines
|
||||
|
||||
substitute some of the invalid sequences with the standard replacement
|
||||
char. this matches Mozilla but not IE which leaves them unchanged (or
|
||||
throws an exception)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
--- kjs/function.cpp
|
||||
+++ kjs/function.cpp
|
||||
@@ -244,11 +244,15 @@ UString decodeURI(ExecState *exec, UStri
|
||||
}
|
||||
|
||||
// UTF-8 transform
|
||||
+ const unsigned long replacementChar = 0xFFFD;
|
||||
unsigned long V;
|
||||
if (n == 2) {
|
||||
unsigned long yyyyy = octets[0] & 0x1F;
|
||||
unsigned long zzzzzz = octets[1] & 0x3F;
|
||||
V = (yyyyy << 6) | zzzzzz;
|
||||
+ // 2-byte sequence overlong for this value?
|
||||
+ if (V < 0xFF)
|
||||
+ V = replacementChar;
|
||||
C = UChar((unsigned short)V);
|
||||
}
|
||||
else if (n == 3) {
|
||||
@@ -256,6 +260,11 @@ UString decodeURI(ExecState *exec, UStri
|
||||
unsigned long yyyyyy = octets[1] & 0x3F;
|
||||
unsigned long zzzzzz = octets[2] & 0x3F;
|
||||
V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz;
|
||||
+ // 3-byte sequence overlong for this value,
|
||||
+ // an invalid value or UTF-16 surrogate?
|
||||
+ if (V < 0x800 || V == 0xFFFE || V == 0xFFFF ||
|
||||
+ (V >= 0xD800 && V <= 0xDFFF))
|
||||
+ V = replacementChar;
|
||||
C = UChar((unsigned short)V);
|
||||
}
|
||||
else {
|
@ -8,7 +8,7 @@
|
||||
|
||||
PORTNAME= kdelibs
|
||||
PORTVERSION= ${KDE_VERSION}
|
||||
PORTREVISION= 1
|
||||
PORTREVISION= 2
|
||||
CATEGORIES= x11 kde ipv6
|
||||
MASTER_SITES= ${MASTER_SITE_KDE}
|
||||
MASTER_SITE_SUBDIR= stable/${PORTVERSION:S/.0//}/src
|
||||
|
38
x11/kdelibs4/files/patch-kdelibs-kjs
Normal file
38
x11/kdelibs4/files/patch-kdelibs-kjs
Normal file
@ -0,0 +1,38 @@
|
||||
------------------------------------------------------------------------
|
||||
r645387 | porten | 2007-03-22 15:01:13 +0100 (Thu, 22 Mar 2007) | 4 lines
|
||||
|
||||
substitute some of the invalid sequences with the standard replacement
|
||||
char. this matches Mozilla but not IE which leaves them unchanged (or
|
||||
throws an exception)
|
||||
|
||||
------------------------------------------------------------------------
|
||||
--- kjs/function.cpp
|
||||
+++ kjs/function.cpp
|
||||
@@ -244,11 +244,15 @@ UString decodeURI(ExecState *exec, UStri
|
||||
}
|
||||
|
||||
// UTF-8 transform
|
||||
+ const unsigned long replacementChar = 0xFFFD;
|
||||
unsigned long V;
|
||||
if (n == 2) {
|
||||
unsigned long yyyyy = octets[0] & 0x1F;
|
||||
unsigned long zzzzzz = octets[1] & 0x3F;
|
||||
V = (yyyyy << 6) | zzzzzz;
|
||||
+ // 2-byte sequence overlong for this value?
|
||||
+ if (V < 0xFF)
|
||||
+ V = replacementChar;
|
||||
C = UChar((unsigned short)V);
|
||||
}
|
||||
else if (n == 3) {
|
||||
@@ -256,6 +260,11 @@ UString decodeURI(ExecState *exec, UStri
|
||||
unsigned long yyyyyy = octets[1] & 0x3F;
|
||||
unsigned long zzzzzz = octets[2] & 0x3F;
|
||||
V = (xxxx << 12) | (yyyyyy << 6) | zzzzzz;
|
||||
+ // 3-byte sequence overlong for this value,
|
||||
+ // an invalid value or UTF-16 surrogate?
|
||||
+ if (V < 0x800 || V == 0xFFFE || V == 0xFFFF ||
|
||||
+ (V >= 0xD800 && V <= 0xDFFF))
|
||||
+ V = replacementChar;
|
||||
C = UChar((unsigned short)V);
|
||||
}
|
||||
else {
|
Loading…
Reference in New Issue
Block a user