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) <ogoffart@woboq.com>bb10
parent
c61cedcc54
commit
64359ad710
|
|
@ -915,7 +915,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<const __m256i *>(a + offset));
|
||||
__m256i b_data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(b + offset));
|
||||
|
|
@ -939,7 +939,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<const __m128i *>(a + offset));
|
||||
__m128i b_data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(b + offset));
|
||||
if (isDifferent(a_data, b_data))
|
||||
|
|
@ -949,7 +949,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<const __m128i *>(a + offset));
|
||||
__m128i b_data = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(b + offset));
|
||||
if (isDifferent(a_data, b_data))
|
||||
|
|
@ -970,7 +970,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<const uint16_t *>(a));
|
||||
uint16x8_t db = vld1q_u16(reinterpret_cast<const uint16_t *>(b));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue