Fix bugs when using a non 0 terminated QLatin1String
authorLars Knoll <lars.knoll@nokia.com>
Sun, 29 Jan 2012 18:53:30 +0000 (19:53 +0100)
committerQt by Nokia <qt-info@nokia.com>
Mon, 30 Jan 2012 22:27:35 +0000 (23:27 +0100)
A few methods in QString still assumed that QLatin1String
is always 0 terminated. Change this to rely on the size
provided by QLatin1String instead.

Change-Id: I9145a46e52ed8811f3b4e3d72d8a81a12588760a
Reviewed-by: Kevin Simons <kevin.simons@nokia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
src/corelib/tools/qstring.cpp
tests/auto/corelib/tools/qstring/tst_qstring.cpp

index b7d0e46..fd9f934 100644 (file)
@@ -162,7 +162,7 @@ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const u
 }
 
 // Case-insensitive comparison between a Unicode string and a QLatin1String
-static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b)
+static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b, const uchar *be)
 {
     if (a == 0) {
         if (b == 0)
@@ -172,7 +172,11 @@ static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b)
     if (b == 0)
         return -1;
 
-    while (a < ae && *b) {
+    const ushort *e = ae;
+    if (be - b < ae - a)
+        e = a + (be - b);
+
+    while (a < e) {
         int diff = foldCase(*a) - foldCase(*b);
         if ((diff))
             return diff;
@@ -180,7 +184,7 @@ static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b)
         ++b;
     }
     if (a == ae) {
-        if (!*b)
+        if (b == be)
             return 0;
         return -1;
     }
@@ -1455,7 +1459,7 @@ QString &QString::insert(int i, const QLatin1String &str)
     if (i < 0 || !s || !(*s))
         return *this;
 
-    int len = qstrlen(str.latin1());
+    int len = str.size();
     expand(qMax(d->size, i) + len - 1);
 
     ::memmove(d->data() + i + len, d->data() + i, (d->size - i - len) * sizeof(QChar));
@@ -1556,7 +1560,7 @@ QString &QString::append(const QLatin1String &str)
 {
     const uchar *s = (const uchar *)str.latin1();
     if (s) {
-        int len = qstrlen((char *)s);
+        int len = str.size();
         if (d->ref != 1 || d->size + len > int(d->alloc))
             realloc(grow(d->size + len));
         ushort *i = d->data() + d->size;
@@ -2053,11 +2057,11 @@ QString &QString::replace(const QLatin1String &before,
                           const QLatin1String &after,
                           Qt::CaseSensitivity cs)
 {
-    int alen = qstrlen(after.latin1());
+    int alen = after.size();
     QVarLengthArray<ushort> a(alen);
     for (int i = 0; i < alen; ++i)
         a[i] = (uchar)after.latin1()[i];
-    int blen = qstrlen(before.latin1());
+    int blen = before.size();
     QVarLengthArray<ushort> b(blen);
     for (int i = 0; i < blen; ++i)
         b[i] = (uchar)before.latin1()[i];
@@ -4606,22 +4610,31 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
                             Qt::CaseSensitivity cs)
 {
     const ushort *uc = reinterpret_cast<const ushort *>(data1);
-    const ushort *e = uc + length1;
+    const ushort *uce = uc + length1;
     const uchar *c = (uchar *)s2.latin1();
 
     if (!c)
         return length1;
 
     if (cs == Qt::CaseSensitive) {
-        while (uc < e && *c && *uc == *c)
+        const ushort *e = uc + length1;
+        if (s2.size() < length1)
+            e = uc + s2.size();
+        while (uc < e) {
+            int diff = *uc - *c;
+            if (diff)
+                return diff;
             uc++, c++;
+        }
 
-        if (uc == e)
-            return -*c;
-
-        return *uc - *c;
+        if (uc == uce) {
+            if (c == (const uchar *)s2.latin1() + s2.size())
+                return 0;
+            return -1;
+        }
+        return 1;
     } else {
-        return ucstricmp(uc, e, c);
+        return ucstricmp(uc, uce, c, c + s2.size());
     }
 }
 
@@ -7174,6 +7187,11 @@ QString &QString::setRawData(const QChar *unicode, int size)
     Returns the Latin-1 string stored in this object.
 */
 
+/*! \fn int QLatin1String::size() const
+
+    Returns the size of the Latin-1 string stored in this object.
+*/
+
 /*! \fn bool QLatin1String::operator==(const QString &other) const
 
     Returns true if this string is equal to string \a other;
@@ -7329,37 +7347,37 @@ QString &QString::setRawData(const QChar *unicode, int size)
 
 
 
-/* \fn bool operator==(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator==(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically equal to string \a s2; otherwise
    returns false.
 */
-/* \fn bool operator!=(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator!=(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically unequal to string \a s2; otherwise
    returns false.
 */
-/* \fn bool operator<(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator<(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically smaller than string \a s2; otherwise
    returns false.
 */
-/* \fn bool operator<=(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator<=(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically smaller than or equal to string \a s2; otherwise
    returns false.
 */
-/* \fn bool operator>(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator>(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically greater than string \a s2; otherwise
    returns false.
 */
-/* \fn bool operator>=(const QLatin1String &s1, const QLatin1String &s2)
+/*! \fn bool operator>=(const QLatin1String &s1, const QLatin1String &s2)
    \relates QLatin1String
 
    Returns true if string \a s1 is lexically greater than or equal to
@@ -7683,6 +7701,9 @@ bool operator==(const QString &s1,const QStringRef &s2)
 */
 bool operator==(const QLatin1String &s1, const QStringRef &s2)
 {
+    if (s1.size() != s2.size())
+        return false;
+
     const ushort *uc = reinterpret_cast<const ushort *>(s2.unicode());
     const ushort *e = uc + s2.size();
     const uchar *c = reinterpret_cast<const uchar *>(s1.latin1());
index 44c196d..2a94943 100644 (file)
@@ -4798,6 +4798,13 @@ void tst_QString::compare()
         QCOMPARE(sign(QString::compare(s1, QLatin1String(s2.toLatin1()), Qt::CaseInsensitive)), cir);
         QCOMPARE(sign(QStringRef::compare(r1, QLatin1String(s2.toLatin1()))), csr);
         QCOMPARE(sign(QStringRef::compare(r1, QLatin1String(s2.toLatin1()), Qt::CaseInsensitive)), cir);
+        QByteArray l1 = s2.toLatin1();
+        l1 += "x";
+        QLatin1String l1str(l1.constData(), l1.size() - 1);
+        QCOMPARE(sign(QString::compare(s1, l1str)), csr);
+        QCOMPARE(sign(QString::compare(s1, l1str, Qt::CaseInsensitive)), cir);
+        QCOMPARE(sign(QStringRef::compare(r1, l1str)), csr);
+        QCOMPARE(sign(QStringRef::compare(r1, l1str, Qt::CaseInsensitive)), cir);
     }
 
     if (isLatin(s1)) {