Fix and simplify QString::mid
authorJoão Abecasis <joao.abecasis@nokia.com>
Mon, 13 Feb 2012 23:02:08 +0000 (00:02 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 14 Feb 2012 11:50:14 +0000 (12:50 +0100)
'position' was being used to initialize 'n' before being fully
validated. To compensate for this, the code attempted to fix 'n' once
'position' was found to be invalid (negative). This would, however, also
attempt to "fix" a perfectly valid value of 'n'.

By fully validating 'position' beforehand we avoid this trap and can
safely use it to validate and reset 'n', as needed.

Arithmetic for boundary conditions of 'n' was rearranged to avoid
triggering integer overflow.

Removed explicit check for shared_null, as the same behaviour can be
supported without it.

Change-Id: Ie9bff7b8137a74f55c7dcfe629bd569045e28f3c
Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
src/corelib/tools/qstring.cpp
tests/auto/corelib/tools/qstring/tst_qstring.cpp

index 28e8b6b..e12cf1f 100644 (file)
@@ -3391,15 +3391,11 @@ QString QString::right(int n) const
 
 QString QString::mid(int position, int n) const
 {
-    if (d == &shared_null.str || position > d->size)
+    if (position > d->size)
         return QString();
-    if (n < 0)
-        n = d->size - position;
-    if (position < 0) {
-        n += position;
+    if (position < 0)
         position = 0;
-    }
-    if (n + position > d->size)
+    if (n < 0 || n > d->size - position)
         n = d->size - position;
     if (position == 0 && n == d->size)
         return *this;
@@ -8061,15 +8057,11 @@ QStringRef QString::rightRef(int n) const
 
 QStringRef QString::midRef(int position, int n) const
 {
-    if (d == &shared_null.str || position > d->size)
+    if (position > d->size)
         return QStringRef();
-    if (n < 0)
-        n = d->size - position;
-    if (position < 0) {
-        n += position;
+    if (position < 0)
         position = 0;
-    }
-    if (n + position > d->size)
+    if (n < 0 || n > d->size - position)
         n = d->size - position;
     return QStringRef(this, position, n);
 }
index 37d80af..7dd801b 100644 (file)
@@ -1429,16 +1429,51 @@ void tst_QString::mid()
     QVERIFY(a.mid(9999).isNull());
     QVERIFY(a.mid(9999,1).isNull());
 
+    QCOMPARE(a.mid(-1, 6), QString("ABCDEF"));
+    QCOMPARE(a.mid(-100, 6), QString("ABCDEF"));
+    QVERIFY(a.mid(INT_MAX).isNull());
+    QVERIFY(a.mid(INT_MAX, INT_MAX).isNull());
+    QCOMPARE(a.mid(-5, INT_MAX), a);
+    QCOMPARE(a.mid(-1, INT_MAX), a);
+    QCOMPARE(a.mid(0, INT_MAX), a);
+    QCOMPARE(a.mid(1, INT_MAX), QString("BCDEFGHIEfGEFG"));
+    QCOMPARE(a.mid(5, INT_MAX), QString("FGHIEfGEFG"));
+    QVERIFY(a.mid(20, INT_MAX).isNull());
+    QCOMPARE(a.mid(-1, -1), a);
+
     QString n;
     QVERIFY(n.mid(3,3).isNull());
     QVERIFY(n.mid(0,0).isNull());
     QVERIFY(n.mid(9999,0).isNull());
     QVERIFY(n.mid(9999,1).isNull());
 
+    QVERIFY(n.mid(-1, 6).isNull());
+    QVERIFY(n.mid(-100, 6).isNull());
+    QVERIFY(n.mid(INT_MAX).isNull());
+    QVERIFY(n.mid(INT_MAX, INT_MAX).isNull());
+    QVERIFY(n.mid(-5, INT_MAX).isNull());
+    QVERIFY(n.mid(-1, INT_MAX).isNull());
+    QVERIFY(n.mid(0, INT_MAX).isNull());
+    QVERIFY(n.mid(1, INT_MAX).isNull());
+    QVERIFY(n.mid(5, INT_MAX).isNull());
+    QVERIFY(n.mid(20, INT_MAX).isNull());
+    QVERIFY(n.mid(-1, -1).isNull());
+
     QString x = "Nine pineapples";
     QCOMPARE(x.mid(5, 4), QString("pine"));
     QCOMPARE(x.mid(5), QString("pineapples"));
 
+    QCOMPARE(x.mid(-1, 6), QString("Nine p"));
+    QCOMPARE(x.mid(-100, 6), QString("Nine p"));
+    QVERIFY(x.mid(INT_MAX).isNull());
+    QVERIFY(x.mid(INT_MAX, INT_MAX).isNull());
+    QCOMPARE(x.mid(-5, INT_MAX), x);
+    QCOMPARE(x.mid(-1, INT_MAX), x);
+    QCOMPARE(x.mid(0, INT_MAX), x);
+    QCOMPARE(x.mid(1, INT_MAX), QString("ine pineapples"));
+    QCOMPARE(x.mid(5, INT_MAX), QString("pineapples"));
+    QVERIFY(x.mid(20, INT_MAX).isNull());
+    QCOMPARE(x.mid(-1, -1), x);
 }
 
 void tst_QString::midRef()
@@ -1455,16 +1490,51 @@ void tst_QString::midRef()
     QVERIFY(a.midRef(9999).toString().isEmpty());
     QVERIFY(a.midRef(9999,1).toString().isEmpty());
 
+    QCOMPARE(a.midRef(-1, 6).toString(), QString("ABCDEF"));
+    QCOMPARE(a.midRef(-100, 6).toString(), QString("ABCDEF"));
+    QVERIFY(a.midRef(INT_MAX).isNull());
+    QVERIFY(a.midRef(INT_MAX, INT_MAX).isNull());
+    QCOMPARE(a.midRef(-5, INT_MAX).toString(), a);
+    QCOMPARE(a.midRef(-1, INT_MAX).toString(), a);
+    QCOMPARE(a.midRef(0, INT_MAX).toString(), a);
+    QCOMPARE(a.midRef(1, INT_MAX).toString(), QString("BCDEFGHIEfGEFG"));
+    QCOMPARE(a.midRef(5, INT_MAX).toString(), QString("FGHIEfGEFG"));
+    QVERIFY(a.midRef(20, INT_MAX).isNull());
+    QCOMPARE(a.midRef(-1, -1).toString(), a);
+
     QString n;
     QVERIFY(n.midRef(3,3).toString().isEmpty());
     QVERIFY(n.midRef(0,0).toString().isEmpty());
     QVERIFY(n.midRef(9999,0).toString().isEmpty());
     QVERIFY(n.midRef(9999,1).toString().isEmpty());
 
+    QVERIFY(n.midRef(-1, 6).isNull());
+    QVERIFY(n.midRef(-100, 6).isNull());
+    QVERIFY(n.midRef(INT_MAX).isNull());
+    QVERIFY(n.midRef(INT_MAX, INT_MAX).isNull());
+    QVERIFY(n.midRef(-5, INT_MAX).isNull());
+    QVERIFY(n.midRef(-1, INT_MAX).isNull());
+    QVERIFY(n.midRef(0, INT_MAX).isNull());
+    QVERIFY(n.midRef(1, INT_MAX).isNull());
+    QVERIFY(n.midRef(5, INT_MAX).isNull());
+    QVERIFY(n.midRef(20, INT_MAX).isNull());
+    QVERIFY(n.midRef(-1, -1).isNull());
+
     QString x = "Nine pineapples";
     QCOMPARE(x.midRef(5, 4).toString(), QString("pine"));
     QCOMPARE(x.midRef(5).toString(), QString("pineapples"));
 
+    QCOMPARE(x.midRef(-1, 6).toString(), QString("Nine p"));
+    QCOMPARE(x.midRef(-100, 6).toString(), QString("Nine p"));
+    QVERIFY(x.midRef(INT_MAX).isNull());
+    QVERIFY(x.midRef(INT_MAX, INT_MAX).isNull());
+    QCOMPARE(x.midRef(-5, INT_MAX).toString(), x);
+    QCOMPARE(x.midRef(-1, INT_MAX).toString(), x);
+    QCOMPARE(x.midRef(0, INT_MAX).toString(), x);
+    QCOMPARE(x.midRef(1, INT_MAX).toString(), QString("ine pineapples"));
+    QCOMPARE(x.midRef(5, INT_MAX).toString(), QString("pineapples"));
+    QVERIFY(x.midRef(20, INT_MAX).isNull());
+    QCOMPARE(x.midRef(-1, -1).toString(), x);
 }
 
 void tst_QString::stringRef()