QByteArray: fix lastIndexOf for char values with set sign bit
lastIndexOf will convert the `needle` to unsigned char, which is then
'upcast' to int, before we search. But the string itself was searched
using signed char, meaning any values with the signed bit set would
mismatch.
Add tests for indexOf and lastIndexOf.
Amends 4c12ae7e67
Fixes: QTBUG-128199
Change-Id: I0ce7d7d9741f21650ef6f0f012a94e00d84a0f02
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit 7b1f3bdc503ea7aceacc9fa8d388d843f1d7b131)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
bb10
parent
833c0040cb
commit
5caa31cb21
|
|
@ -74,10 +74,10 @@ const void *qmemrchr(const void *s, int needle, size_t size) noexcept
|
|||
#if QT_CONFIG(memrchr)
|
||||
return memrchr(s, needle, size);
|
||||
#endif
|
||||
auto b = static_cast<const char *>(s);
|
||||
const char *n = b + size;
|
||||
auto b = static_cast<const uchar *>(s);
|
||||
const uchar *n = b + size;
|
||||
while (n-- != b) {
|
||||
if (*n == needle)
|
||||
if (*n == uchar(needle))
|
||||
return n;
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -119,6 +119,11 @@ private slots:
|
|||
void isUpper();
|
||||
void isLower();
|
||||
|
||||
void indexOf_data();
|
||||
void indexOf();
|
||||
void lastIndexOf_data();
|
||||
void lastIndexOf();
|
||||
|
||||
void macTypes();
|
||||
|
||||
void stdString();
|
||||
|
|
@ -2588,6 +2593,93 @@ void tst_QByteArray::isLower()
|
|||
QVERIFY(QByteArray("`abyz{").isLower());
|
||||
}
|
||||
|
||||
using ByteArrayOrChar = std::variant<QByteArray, char>;
|
||||
void tst_QByteArray::indexOf_data()
|
||||
{
|
||||
qRegisterMetaType<ByteArrayOrChar>();
|
||||
QTest::addColumn<QByteArray>("haystack");
|
||||
QTest::addColumn<ByteArrayOrChar>("needle");
|
||||
QTest::addColumn<int>("expectedIndex");
|
||||
QTest::addColumn<int>("from");
|
||||
|
||||
const QByteArray haystack = "abc 123 cba \x80 \x08 \x00 \x01 \x81"_ba;
|
||||
|
||||
QTest::newRow("not_found_1_char_string") << haystack << ByteArrayOrChar("d"_ba) << -1 << 0;
|
||||
QTest::newRow("not_found_char") << haystack << ByteArrayOrChar('d') << -1 << 0;
|
||||
|
||||
QTest::newRow("not_found_string") << haystack << ByteArrayOrChar("abcd"_ba) << -1 << 0;
|
||||
QTest::newRow("found_1_char_string") << haystack << ByteArrayOrChar("a"_ba) << 0 << 0;
|
||||
|
||||
QTest::newRow("found_char") << haystack << ByteArrayOrChar('a') << 0 << 0;
|
||||
QTest::newRow("found_string") << haystack << ByteArrayOrChar("cba"_ba) << 8 << 0;
|
||||
|
||||
QTest::newRow("found_empty_string") << haystack << ByteArrayOrChar(""_ba) << 0 << 0;
|
||||
|
||||
QTest::newRow("found_embedded_null") << haystack << ByteArrayOrChar("\x00"_ba) << 16 << 0;
|
||||
QTest::newRow("not_found_terminating_null") << haystack << ByteArrayOrChar("\x00"_ba) << -1 << 17;
|
||||
QTest::newRow("found_char_star_0x80") << haystack << ByteArrayOrChar("\x80"_ba) << 12 << 0;
|
||||
QTest::newRow("found_char_0x80") << haystack << ByteArrayOrChar('\x80') << 12 << 0;
|
||||
QTest::newRow("found_char_0x81") << haystack << ByteArrayOrChar('\x81') << 20 << 0;
|
||||
}
|
||||
|
||||
void tst_QByteArray::indexOf()
|
||||
{
|
||||
QFETCH(QByteArray, haystack);
|
||||
QFETCH(ByteArrayOrChar, needle);
|
||||
QFETCH(int, expectedIndex);
|
||||
QFETCH(int, from);
|
||||
|
||||
if (auto *qba = std::get_if<QByteArray>(&needle)) {
|
||||
QCOMPARE(haystack.indexOf(*qba, from), expectedIndex);
|
||||
} else {
|
||||
char c = std::get<char>(needle);
|
||||
QCOMPARE(haystack.indexOf(c, from), expectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QByteArray::lastIndexOf_data()
|
||||
{
|
||||
qRegisterMetaType<ByteArrayOrChar>();
|
||||
QTest::addColumn<QByteArray>("haystack");
|
||||
QTest::addColumn<ByteArrayOrChar>("needle");
|
||||
QTest::addColumn<int>("expectedIndex");
|
||||
QTest::addColumn<int>("from");
|
||||
|
||||
const QByteArray haystack = "abc 123 cba \x80 \x08 \x00 \x01 \x81"_ba;
|
||||
|
||||
QTest::newRow("not_found_1_char_string") << haystack << ByteArrayOrChar("d"_ba) << -1 << -1;
|
||||
QTest::newRow("not_found_char") << haystack << ByteArrayOrChar('d') << -1 << -1;
|
||||
|
||||
QTest::newRow("not_found_string") << haystack << ByteArrayOrChar("abcd"_ba) << -1 << -1;
|
||||
QTest::newRow("found_1_char_string") << haystack << ByteArrayOrChar("a"_ba) << 10 << -1;
|
||||
|
||||
QTest::newRow("found_char") << haystack << ByteArrayOrChar('a') << 10 << -1;
|
||||
QTest::newRow("found_string") << haystack << ByteArrayOrChar("cba"_ba) << 8 << -1;
|
||||
|
||||
QTest::newRow("found_empty_string") << haystack << ByteArrayOrChar(""_ba) << haystack.size() << -1;
|
||||
|
||||
QTest::newRow("found_embedded_null") << haystack << ByteArrayOrChar("\x00"_ba) << 16 << -1;
|
||||
QTest::newRow("not_found_leading_null") << haystack << ByteArrayOrChar("\x00"_ba) << -1 << 15;
|
||||
QTest::newRow("found_char_star_0x80") << haystack << ByteArrayOrChar("\x80"_ba) << 12 << -1;
|
||||
QTest::newRow("found_char_0x80") << haystack << ByteArrayOrChar('\x80') << 12 << -1;
|
||||
QTest::newRow("found_char_0x81") << haystack << ByteArrayOrChar('\x81') << 20 << -1;
|
||||
}
|
||||
|
||||
void tst_QByteArray::lastIndexOf()
|
||||
{
|
||||
QFETCH(QByteArray, haystack);
|
||||
QFETCH(ByteArrayOrChar, needle);
|
||||
QFETCH(int, expectedIndex);
|
||||
QFETCH(int, from);
|
||||
|
||||
if (auto *qba = std::get_if<QByteArray>(&needle)) {
|
||||
QCOMPARE(haystack.lastIndexOf(*qba, from), expectedIndex);
|
||||
} else {
|
||||
char c = std::get<char>(needle);
|
||||
QCOMPARE(haystack.lastIndexOf(c, from), expectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QByteArray::macTypes()
|
||||
{
|
||||
#ifndef Q_OS_DARWIN
|
||||
|
|
|
|||
Loading…
Reference in New Issue