void movablity_data();
void movablity();
void literals();
+
+ void zeroTermination_data();
+ void zeroTermination();
};
+// Except for QByteArrays initialized with fromRawData(), QByteArray ensures
+// that data() is null-terminated. VERIFY_ZERO_TERMINATION checks that
+// invariant and goes further by testing that the null-character is in writable
+// memory allocated by QByteArray. If the invariant is broken, tools like
+// valgrind should be able to detect this.
+#define VERIFY_ZERO_TERMINATION(ba) \
+ do { \
+ /* Statics could be anything, as can fromRawData() strings */ \
+ QByteArray::DataPtr baDataPtr = ba.data_ptr(); \
+ if (!baDataPtr->ref.isStatic() \
+ && baDataPtr->offset == QByteArray().data_ptr()->offset) { \
+ int baSize = ba.size(); \
+ QCOMPARE(ba.constData()[baSize], '\0'); \
+ \
+ QByteArray baCopy(ba.constData(), baSize); \
+ if (!baDataPtr->ref.isShared()) { \
+ /* Don't detach, assumes no setSharable support */ \
+ char *baData = ba.data(); \
+ baData[baSize] = 'x'; \
+ \
+ QCOMPARE(ba.constData()[baSize], 'x'); \
+ QCOMPARE(ba, baCopy); \
+ \
+ baData[baSize] = '\0'; /* Sanity restored */ \
+ } \
+ } \
+ } while (false) \
+ /**/
+
struct StaticByteArrays {
struct Standard {
QByteArrayData data;
void tst_QByteArray::qCompress()
{
QFETCH( QByteArray, ba );
+
QByteArray compressed = ::qCompress( ba );
- QTEST( ::qUncompress( compressed ), "ba" );
+ QByteArray uncompressed = ::qUncompress(compressed);
+
+ QCOMPARE(uncompressed, ba);
+ VERIFY_ZERO_TERMINATION(compressed);
+ VERIFY_ZERO_TERMINATION(uncompressed);
}
void tst_QByteArray::qUncompressCorruptedData_data()
QByteArray res;
res = ::qUncompress(in);
QCOMPARE(res, QByteArray());
+ VERIFY_ZERO_TERMINATION(res);
res = ::qUncompress(in + "blah");
QCOMPARE(res, QByteArray());
+ VERIFY_ZERO_TERMINATION(res);
#else
QSKIP("This test freezes on this platform");
#endif
{
QString s = "Hello, I'm a string.";
QByteArray ba = ::qUncompress(::qCompress(s.toLocal8Bit()));
- QVERIFY((int) *(ba.data() + ba.size()) == 0);
+ VERIFY_ZERO_TERMINATION(ba);
}
#endif
QVERIFY(cba.constData()[1] == 'b');
QVERIFY(cba.constData()[2] == 'c');
QVERIFY(cba.constData()[3] == '\0');
+ VERIFY_ZERO_TERMINATION(cba);
}
void tst_QByteArray::leftJustified()
QByteArray arr = QByteArray::fromBase64(base64);
QCOMPARE(arr, rawdata);
+ VERIFY_ZERO_TERMINATION(arr);
QByteArray arr64 = rawdata.toBase64();
QCOMPARE(arr64, base64);
+ VERIFY_ZERO_TERMINATION(arr64);
}
//different from the previous test as the input are invalid
src.chop(choplength);
QCOMPARE(src, expected);
+ VERIFY_ZERO_TERMINATION(src);
}
void tst_QByteArray::prepend()
{
QByteArray ba("foo");
QCOMPARE(ba.prepend((char*)0), QByteArray("foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.prepend(QByteArray()), QByteArray("foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.prepend("1"), QByteArray("1foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.prepend(QByteArray("2")), QByteArray("21foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.prepend('3'), QByteArray("321foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.prepend("\0 ", 2), QByteArray::fromRawData("\0 321foo", 8));
+ VERIFY_ZERO_TERMINATION(ba);
}
void tst_QByteArray::prependExtended_data()
QCOMPARE(QByteArray("").prepend(array), QByteArray("data"));
QCOMPARE(array.prepend((char*)0), QByteArray("data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.prepend(QByteArray()), QByteArray("data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.prepend("1"), QByteArray("1data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.prepend(QByteArray("2")), QByteArray("21data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.prepend('3'), QByteArray("321data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.prepend("\0 ", 2), QByteArray::fromRawData("\0 321data", 9));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.size(), 9);
}
{
QByteArray ba("foo");
QCOMPARE(ba.append((char*)0), QByteArray("foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append(QByteArray()), QByteArray("foo"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append("1"), QByteArray("foo1"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append(QByteArray("2")), QByteArray("foo12"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append('3'), QByteArray("foo123"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append("\0"), QByteArray("foo123"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.append("\0", 1), QByteArray::fromRawData("foo123\0", 7));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.size(), 7);
}
QCOMPARE(QByteArray("").append(array), QByteArray("data"));
QCOMPARE(array.append((char*)0), QByteArray("data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append(QByteArray()), QByteArray("data"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append("1"), QByteArray("data1"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append(QByteArray("2")), QByteArray("data12"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append('3'), QByteArray("data123"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append("\0"), QByteArray("data123"));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.append("\0", 1), QByteArray::fromRawData("data123\0", 8));
+ VERIFY_ZERO_TERMINATION(array);
QCOMPARE(array.size(), 8);
}
{
QByteArray ba("Meal");
QCOMPARE(ba.insert(1, QByteArray("ontr")), QByteArray("Montreal"));
+ VERIFY_ZERO_TERMINATION(ba);
QCOMPARE(ba.insert(ba.size(), "foo"), QByteArray("Montrealfoo"));
+ VERIFY_ZERO_TERMINATION(ba);
ba = QByteArray("13");
QCOMPARE(ba.insert(1, QByteArray("2")), QByteArray("123"));
+ VERIFY_ZERO_TERMINATION(ba);
ba = "ac";
QCOMPARE(ba.insert(1, 'b'), QByteArray("abc"));
QCOMPARE(ba.size(), 3);
+ VERIFY_ZERO_TERMINATION(ba);
ba = "ikl";
QCOMPARE(ba.insert(1, "j"), QByteArray("ijkl"));
QCOMPARE(ba.size(), 4);
+ VERIFY_ZERO_TERMINATION(ba);
ba = "ab";
QCOMPARE(ba.insert(1, "\0X\0", 3), QByteArray::fromRawData("a\0X\0b", 5));
QCOMPARE(ba.size(), 5);
+ VERIFY_ZERO_TERMINATION(ba);
}
void tst_QByteArray::insertExtended_data()
QFETCH(QByteArray, array);
QCOMPARE(array.insert(1, "i"), QByteArray("diata"));
QCOMPARE(array.size(), 5);
+ VERIFY_ZERO_TERMINATION(array);
}
void tst_QByteArray::remove_data()
QFETCH(int, length);
QFETCH(QByteArray, expected);
QCOMPARE(src.remove(position, length), expected);
+ VERIFY_ZERO_TERMINATION(src);
}
void tst_QByteArray::replace_data()
QCOMPARE(str1.replace(pos, len, after).constData(), expected.constData());
QCOMPARE(str2.replace(pos, len, after.data()), expected);
+ VERIFY_ZERO_TERMINATION(str1);
+ VERIFY_ZERO_TERMINATION(str2);
}
void tst_QByteArray::replaceWithSpecifiedLength()
const char _expected[] = "zxc\0vbcdefghjk";
QByteArray expected(_expected,sizeof(_expected)-1);
QCOMPARE(ba,expected);
+ VERIFY_ZERO_TERMINATION(ba);
}
void tst_QByteArray::indexOf_data()
data[0] = 'Y';
}
QVERIFY(arr.at(0) == 'X');
+ VERIFY_ZERO_TERMINATION(arr);
}
void tst_QByteArray::toFromHex_data()
QFETCH(QByteArray, hex_alt1);
{
- const QByteArray th = str.toHex();
+ QByteArray th = str.toHex();
QCOMPARE(th.size(), hex.size());
QCOMPARE(th, hex);
+ VERIFY_ZERO_TERMINATION(th);
}
{
- const QByteArray fh = QByteArray::fromHex(hex);
+ QByteArray fh = QByteArray::fromHex(hex);
QCOMPARE(fh.size(), str.size());
QCOMPARE(fh, str);
+ VERIFY_ZERO_TERMINATION(fh);
}
QCOMPARE(QByteArray::fromHex(hex_alt1), str);
QByteArray data = arr.toPercentEncoding();
QCOMPARE(QString(data), QString("Qt%20is%20great%21"));
QCOMPARE(QByteArray::fromPercentEncoding(data), arr);
+ VERIFY_ZERO_TERMINATION(data);
data = arr.toPercentEncoding("! ", "Qt");
QCOMPARE(QString(data), QString("%51%74 is grea%74!"));
QCOMPARE(QByteArray::fromPercentEncoding(data), arr);
+ VERIFY_ZERO_TERMINATION(data);
data = arr.toPercentEncoding(QByteArray(), "abcdefghijklmnopqrstuvwxyz", 'Q');
QCOMPARE(QString(data), QString("Q51Q74Q20Q69Q73Q20Q67Q72Q65Q61Q74Q21"));
QCOMPARE(QByteArray::fromPercentEncoding(data, 'Q'), arr);
+ VERIFY_ZERO_TERMINATION(data);
// verify that to/from percent encoding preserves nullity
arr = "";
QVERIFY(!arr.toPercentEncoding().isNull());
QVERIFY(QByteArray::fromPercentEncoding("").isEmpty());
QVERIFY(!QByteArray::fromPercentEncoding("").isNull());
+ VERIFY_ZERO_TERMINATION(arr);
arr = QByteArray();
QVERIFY(arr.isEmpty());
QVERIFY(arr.toPercentEncoding().isNull());
QVERIFY(QByteArray::fromPercentEncoding(QByteArray()).isEmpty());
QVERIFY(QByteArray::fromPercentEncoding(QByteArray()).isNull());
+ VERIFY_ZERO_TERMINATION(arr);
}
void tst_QByteArray::fromPercentEncoding_data()
QFETCH(int, count);
QCOMPARE(string.repeated(count), expected);
+
+ QByteArray repeats = string.repeated(count);
+ VERIFY_ZERO_TERMINATION(repeats);
}
void tst_QByteArray::repeated_data() const
copy[0] = 'S';
QCOMPARE(str, QByteArray("str"));
+ VERIFY_ZERO_TERMINATION(copy);
}
{
str[0] = 'S';
QCOMPARE(buf[0], char('s'));
+ VERIFY_ZERO_TERMINATION(str);
}
{
str[0] = 'S';
QCOMPARE(buf[0], char('s'));
+ VERIFY_ZERO_TERMINATION(str);
}
}
QByteArray qba;
qba.reserve(capacity);
QVERIFY(qba.capacity() == capacity);
- char *data = qba.data();
+ VERIFY_ZERO_TERMINATION(qba);
+ char *data = qba.data();
for (int i = 0; i < capacity; i++) {
qba.resize(i);
QVERIFY(capacity == qba.capacity());
QVERIFY(data == qba.data());
+ VERIFY_ZERO_TERMINATION(qba);
}
QByteArray nil1, nil2;
nil1.reserve(0);
+ VERIFY_ZERO_TERMINATION(nil1);
nil2.squeeze();
+ VERIFY_ZERO_TERMINATION(nil2);
nil1.squeeze();
+ VERIFY_ZERO_TERMINATION(nil1);
nil2.reserve(0);
+ VERIFY_ZERO_TERMINATION(nil2);
}
void tst_QByteArray::reserveExtended_data()
void tst_QByteArray::reserveExtended()
{
QFETCH(QByteArray, array);
+
array.reserve(1024);
QVERIFY(array.capacity() == 1024);
QCOMPARE(array, QByteArray("data"));
+ VERIFY_ZERO_TERMINATION(array);
+
array.squeeze();
QCOMPARE(array, QByteArray("data"));
QCOMPARE(array.capacity(), array.size());
+ VERIFY_ZERO_TERMINATION(array);
}
void tst_QByteArray::movablity_data()
QVERIFY(str == "abcd");
QVERIFY(str.data_ptr()->ref.isStatic());
QVERIFY(str.data_ptr()->offset == sizeof(QByteArrayData));
+ VERIFY_ZERO_TERMINATION(str);
const char *s = str.constData();
QByteArray str2 = str;
// detach on non const access
QVERIFY(str.data() != s);
+ VERIFY_ZERO_TERMINATION(str);
QVERIFY(str2.constData() == s);
QVERIFY(str2.data() != s);
+ VERIFY_ZERO_TERMINATION(str2);
#else
QSKIP("Only tested on c++0x compliant compiler or gcc");
#endif
}
+void tst_QByteArray::zeroTermination_data()
+{
+ movablity_data();
+}
+
+void tst_QByteArray::zeroTermination()
+{
+ QFETCH(QByteArray, array);
+ VERIFY_ZERO_TERMINATION(array);
+}
+
const char globalChar = '1';
QTEST_APPLESS_MAIN(tst_QByteArray)