diff options
author | Peter Wu <peter@lekensteyn.nl> | 2014-07-02 17:00:15 +0200 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2014-07-06 22:53:34 +0000 |
commit | ec6a22dc3ba8e2d438b34d892d6a40e1be2a28f2 (patch) | |
tree | 96040409382fbc9442b1e868cf9631e111dbd0cd | |
parent | 49bc1047be0ed7b1bafcffb0f77e84aead056c0a (diff) | |
download | wireshark-ec6a22dc3ba8e2d438b34d892d6a40e1be2a28f2.tar.gz |
Workaround for ASAN failure in _ws_mempbrk_sse42
When ASAN is enabled, a false buffer overflow warning is raised. It is
a false positive since everything starting at '\0' will get ignored by
the PCMPISTRI instruction (see Intel(r) SSE4 Programming Reference,
5.3.1.5 "Valid/Invalid Override of Comparisons", and 5.3.1.2
"Aggregrate Operation", case "Equal any").
Concerns about reading past the end of the page turns out to be false,
there always seem to be a valid page after the current one (for static
and heap memory at least). It is an non-issue since strlen also does
not have issues with this.
Rather than fully disabling SSE 4.2 and using the fallback
implementation for ASAN-enabled builds, read the set of characters from
'a' into the mask without a 128-bit read and then still use SSE 4.2
for the actual query.
Bug: 10214
Change-Id: Ie4a526e60b43bfc08dd1d821556766f14a49be4d
Reviewed-on: https://code.wireshark.org/review/2618
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Reviewed-by: Evan Huus <eapache@gmail.com>
-rw-r--r-- | wsutil/ws_mempbrk_sse42.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/wsutil/ws_mempbrk_sse42.c b/wsutil/ws_mempbrk_sse42.c index 364021b04b..1eaab4cb29 100644 --- a/wsutil/ws_mempbrk_sse42.c +++ b/wsutil/ws_mempbrk_sse42.c @@ -34,6 +34,12 @@ #include <string.h> #include "ws_mempbrk.h" +/* __has_feature(address_sanitizer) is used later for Clang, this is for + * compatibility with other compilers (such as GCC and MSVC) */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + #define cast_128aligned__m128i(p) ((const __m128i *) (const void *) (p)) /* Helper for variable shifts of SSE registers. @@ -93,6 +99,24 @@ _ws_mempbrk_sse42(const char *s, size_t slen, const char *a) __m128i mask; int offset; +#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) + { + /* As 'a' is not guarantueed to have a size of at least 16 bytes, and is not + * aligned, _mm_load_si128() cannot be used when ASAN is enabled. That + * triggers a buffer overflow which is harmless as 'a' is guaranteed to be + * '\0' terminated, and the PCMISTRI instruction always ignored everything + * starting from EOS ('\0'). A false positive indeed. */ + size_t length; + + length = strlen(a); + /* Don't use SSE4.2 if the length of A > 16. */ + if (length > 16) + return _ws_mempbrk(s, slen, a); + + mask = _mm_setzero_si128(); + memcpy(&mask, a, length); + } +#else /* else if ASAN is disabled */ offset = (int) ((size_t) a & 15); aligned = (const char *) ((size_t) a & -16L); if (offset != 0) @@ -142,6 +166,7 @@ _ws_mempbrk_sse42(const char *s, size_t slen, const char *a) return _ws_mempbrk(s, slen, a); } } +#endif /* ASAN disabled */ offset = (int) ((size_t) s & 15); aligned = (const char *) ((size_t) s & -16L); |