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 4c12ae7e67abc3d9b5847f6b61177ede3ee3203b 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>
This commit is contained in:
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…
x
Reference in New Issue
Block a user