From 5839535c9fb5d511ed8eec9250ac7ec52fe4e1f6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 7 Jan 2020 16:25:37 -0800 Subject: ucstrncmp: Fix UBSan report of array overflowing The expression "a + offset + N" will eventually calculate an address past the end of a, since we are comparing to end. That's undefined behavior. Instead, calculate end - a and compare that to offset + N. This commit subtracts "a" from both sides of the inequalities and swaps the two sides to make them obey Qt coding style. Testing with GCC 9 (which is the only one I care about) shows the compiler generates the same code. Fixes: QTBUG-81218 Change-Id: Id84da383373844f3a4b0fffd15e7c1ab904daccd Reviewed-by: Olivier Goffart (Woboq GmbH) (cherry picked from commit 64359ad710756e7cca5ca553521b2aada18fb0fe) --- src/corelib/tools/qstring.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ad2e8bbcd8..a04f48ef8e 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -918,7 +918,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l) }; // we're going to read a[0..15] and b[0..15] (32 bytes) - for ( ; a + offset + 16 <= end; offset += 16) { + for ( ; end - a >= offset + 16; offset += 16) { #ifdef __AVX2__ __m256i a_data = _mm256_loadu_si256(reinterpret_cast(a + offset)); __m256i b_data = _mm256_loadu_si256(reinterpret_cast(b + offset)); @@ -942,7 +942,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l) } // we're going to read a[0..7] and b[0..7] (16 bytes) - if (a + offset + 8 <= end) { + if (end - a >= offset + 8) { __m128i a_data = _mm_loadu_si128(reinterpret_cast(a + offset)); __m128i b_data = _mm_loadu_si128(reinterpret_cast(b + offset)); if (isDifferent(a_data, b_data)) @@ -952,7 +952,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l) } // we're going to read a[0..3] and b[0..3] (8 bytes) - if (a + offset + 4 <= end) { + if (end - a >= offset + 4) { __m128i a_data = _mm_loadl_epi64(reinterpret_cast(a + offset)); __m128i b_data = _mm_loadl_epi64(reinterpret_cast(b + offset)); if (isDifferent(a_data, b_data)) @@ -973,7 +973,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, size_t l) if (l >= 8) { const QChar *end = a + l; const uint16x8_t mask = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 }; - while (a + 7 < end) { + while (end - a > 7) { uint16x8_t da = vld1q_u16(reinterpret_cast(a)); uint16x8_t db = vld1q_u16(reinterpret_cast(b)); -- cgit v1.2.3