From d25e5e2cb78a2e2f2a1791fed250421ce9eefc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 4 Feb 2025 11:36:17 +0100 Subject: [PATCH] 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 --- src/corelib/text/qbytearray.cpp | 8 ++++---- tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 77118ea5d73..2cc55ef0138 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -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; diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp index df7e14ef3c7..979b79c6709 100644 --- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp @@ -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()