From adb8478b619138cbfbcc580c9955975328d2e755 Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Mon, 14 Sep 2015 11:23:31 -0400 Subject: [PATCH] include/inline_memory: out-of-bounds read on unaligned memory When checking if a >=16 byte unaligned buffer is zeroed, the 32bit check will read outside the buffer memory range. Fixes: #13082 Signed-off-by: Jason Dillaman --- src/include/inline_memory.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/include/inline_memory.h b/src/include/inline_memory.h index 33c6bc0ea0d..f2166826b76 100644 --- a/src/include/inline_memory.h +++ b/src/include/inline_memory.h @@ -77,13 +77,9 @@ static inline bool mem_is_zero(const char *data, size_t len) bool mem_is_zero(const char *data, size_t len) { - const char *max = data + len; - const char* max32 = data + (len / sizeof(uint32_t))*sizeof(uint32_t); -#if defined(__GNUC__) && defined(__x86_64__) // we do have XMM registers in x86-64, so if we need to check at least - // 16 bytes, make use of them - int left = len; - if (left / sizeof(uint128_t) > 0) { + // 16 bytes, make use of them + if (len / sizeof(uint128_t) > 0) { // align data pointer to 16 bytes, otherwise it'll segfault due to bug // in (at least some) GCC versions (using MOVAPS instead of MOVUPS). // check up to 15 first bytes while at it. @@ -92,10 +88,11 @@ bool mem_is_zero(const char *data, size_t len) return false; } data += sizeof(uint8_t); - left--; + --len; } - const char* max128 = data + (left / sizeof(uint128_t))*sizeof(uint128_t); + const char* data_start = data; + const char* max128 = data + (len / sizeof(uint128_t))*sizeof(uint128_t); while (data < max128) { if (*(uint128_t*)data != 0) { @@ -103,8 +100,11 @@ bool mem_is_zero(const char *data, size_t len) } data += sizeof(uint128_t); } + len -= (data - data_start); } -#endif + + const char* max = data + len; + const char* max32 = data + (len / sizeof(uint32_t))*sizeof(uint32_t); while (data < max32) { if (*(uint32_t*)data != 0) { return false;