]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
include/inline_memory: out-of-bounds read on unaligned memory 5926/head
authorJason Dillaman <dillaman@redhat.com>
Mon, 14 Sep 2015 15:23:31 +0000 (11:23 -0400)
committerJason Dillaman <dillaman@redhat.com>
Mon, 14 Sep 2015 15:27:45 +0000 (11:27 -0400)
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 <dillaman@redhat.com>
src/include/inline_memory.h

index 33c6bc0ea0dceaf96d330dde95363765fff9970b..f2166826b76d2e8a8f09a0d71ef1f1b62874f516 100644 (file)
@@ -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;