Do not use QHash's aeshash() under Clang's sanitizer

aeshash() has a heap-buffer-overflow when the passed in buffer length is
less than 16 bytes (and I expect there's a similar issue when we process
the tail when length is not divisible by 16). Despite being a real issue,
the code has guarding mechanisms to make sure that:
1) no crash happens
2) out-of-range bits are not used in the computation

Disabled the usage of aeshash() under Clang's sanitizer similarly to how
it was done for GCC (apparently it uses its own preprocessor mechanism).
Likely, this will pop up again with MSVC, but I have no clue which
defines it uses

Task-number: QTBUG-87112
Task-number: QTBUG-86051
Change-Id: I614d7b3082e91c9d16e0441649d6a153b222bd2e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Andrei Golubev 2020-10-01 17:28:29 +02:00
parent 623e866d5c
commit 3929fd3c56

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2012 Giuseppe D'Angelo <dangelog@gmail.com>.
** Contact: https://www.qt.io/licensing/
@ -387,11 +387,23 @@ static uint siphash(const uint8_t *in, uint inlen, const uint seed)
}
#endif
#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__) // GCC
# define QHASH_AES_SANITIZER_BUILD
#elif QT_HAS_FEATURE(address_sanitizer) || QT_HAS_FEATURE(thread_sanitizer) // Clang
# define QHASH_AES_SANITIZER_BUILD
#endif
// When built with a sanitizer, aeshash() is rightfully reported to have a
// heap-buffer-overflow issue. However, we consider it to be safe in this
// specific case and overcome the problem by correctly discarding the
// out-of-range bits. To allow building the code with sanitizer,
// QHASH_AES_SANITIZER_BUILD is used to disable aeshash() usage.
#if QT_COMPILER_SUPPORTS_HERE(AES) && QT_COMPILER_SUPPORTS_HERE(SSE4_2) && \
!(defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__))
!defined(QHASH_AES_SANITIZER_BUILD)
# define AESHASH
#undef QHASH_AES_SANITIZER_BUILD
QT_FUNCTION_TARGET(AES)
static size_t aeshash(const uchar *p, size_t len, size_t seed) noexcept
{