QByteArray(View)::lastIndexOf: Guard against needle > haystack

Otherwise we would traverse beyond bounds.

We calculate the delta in sizes between the haystack and the needle and
if this delta is smaller than the starting position
(the `from` argument) then we start from there.

The default value for `from` is size(). With the needle being longer
than the haystack, the delta is negative and we set our starting
position to be the delta, i.e. we start before the start of the
haystack.

[ChangeLog][QtCore][QByteArray/QByteArrayView] Fixed a bug in
lastIndexOf() that could lead to out-of-bounds access when the needle
is longer than the haystack.

Pick-to: 6.9 6.8 6.5 6.2 5.15
Change-Id: Id5cd772f00b0c3c50fbf61b4e888bba5587391ee
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Mårten Nordheim 2025-02-04 11:36:17 +01:00
parent 9afd4f6814
commit d25e5e2cb7
2 changed files with 10 additions and 4 deletions

View File

@ -2755,12 +2755,12 @@ static qsizetype lastIndexOfHelper(const char *haystack, qsizetype l, const char
qsizetype ol, qsizetype from)
{
auto delta = l - ol;
if (from < 0)
from = delta;
if (from < 0 || from > l)
if (from > l)
return -1;
if (from > delta)
if (from < 0 || from > delta)
from = delta;
if (from < 0)
return -1;
const char *end = haystack;
haystack += from;

View File

@ -2665,6 +2665,9 @@ void tst_QByteArray::indexOf_data()
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;
// Make the needle sufficiently large to try to potentially trip boundary guards:
QTest::newRow("needle_larger_than_haystack") << "b"_ba << ByteArrayOrChar(":"_ba.repeated(4096)) << -1 << 0;
}
void tst_QByteArray::indexOf()
@ -2708,6 +2711,9 @@ void tst_QByteArray::lastIndexOf_data()
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;
// Make the needle sufficiently large to try to potentially trip boundary guards:
QTest::newRow("needle_larger_than_haystack") << "b"_ba << ByteArrayOrChar(":"_ba.repeated(4096)) << -1 << 0;
}
void tst_QByteArray::lastIndexOf()