This is an automated email from the ASF dual-hosted git repository.

yangzhg pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-doris.git


The following commit(s) were added to refs/heads/master by this push:
     new d6aebc0  [improvement] make asan work as much as possible (#8148)
d6aebc0 is described below

commit d6aebc0c2c2ef2e84343f24fbd2e1ad0ae2d8cef
Author: dataroaring <[email protected]>
AuthorDate: Tue Feb 22 09:29:22 2022 +0800

    [improvement] make asan work as much as possible (#8148)
    
    * make ASAN poisoning work as much as possible
    
    Before this patch a use after poison is reported like below
    ==19305==ERROR: AddressSanitizer: unknown-crash on address
    0x625000137013 at pc 0x561c44bcf6b8 bp 0x7ffb75a00910 sp 0x7ffb75a000b8
    
    After this patch the use after poison is reported like below
    ==17782==ERROR: AddressSanitizer: use-after-poison on address
    0x625000137033 at pc 0x55633c8f56b8 bp 0x7ff3dc437930 sp 0x7ff3dc43
    
    Before this patch, a false memory usage is reported like below
    ==33080==AddressSanitizer CHECK failed: ../../../../src/libsanitizer/
    asan/asan_allocator.cpp:189 "((old)) == ((kAllocBegMagic))"
---
 be/src/runtime/mem_pool.h | 67 +++++++++++++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 22 deletions(-)

diff --git a/be/src/runtime/mem_pool.h b/be/src/runtime/mem_pool.h
index 04d6236..f51079b 100644
--- a/be/src/runtime/mem_pool.h
+++ b/be/src/runtime/mem_pool.h
@@ -163,6 +163,12 @@ public:
 
     static constexpr int DEFAULT_ALIGNMENT = 8;
 
+#if defined(__SANITIZE_ADDRESS__) || defined(ADDRESS_SANITIZER)
+    static constexpr int DEFAULT_PADDING_SIZE = 0x10;
+#else
+    static constexpr int DEFAULT_PADDING_SIZE = 0x0;
+#endif
+
 private:
     friend class MemPoolTest;
     static const int INITIAL_CHUNK_SIZE = 4 * 1024;
@@ -203,26 +209,48 @@ private:
         return chunks_[current_chunk_idx_].allocated_bytes;
     }
 
+    uint8_t * allocate_from_current_chunk(int64_t size, int alignment) {
+        // Manually ASAN poisoning is complicated and it is hard to make
+        // it work right. There are illustrated examples in
+        // http://blog.hostilefork.com/poison-memory-without-asan/.
+        //
+        // Stacks of use after poison do not provide enough information
+        // to resolve bug, while stacks of use afer free provide.
+        // https://github.com/google/sanitizers/issues/191
+        //
+        // We'd better implement a mempool using malloc/free directly,
+        // thus asan works natively. However we cannot do it in a short
+        // time, so we make manual poisoning work as much as possible.
+        // I refers to https://github.com/mcgov/asan_alignment_example.
+
+        ChunkInfo& info = chunks_[current_chunk_idx_];
+        int64_t aligned_allocated_bytes =
+                BitUtil::RoundUpToPowerOf2(info.allocated_bytes + 
DEFAULT_PADDING_SIZE, alignment);
+        if (aligned_allocated_bytes + size <= info.chunk.size) {
+            // Ensure the requested alignment is respected.
+            int64_t padding = aligned_allocated_bytes - info.allocated_bytes;
+            uint8_t* result = info.chunk.data + aligned_allocated_bytes;
+            ASAN_UNPOISON_MEMORY_REGION(result, size);
+            DCHECK_LE(info.allocated_bytes + size, info.chunk.size);
+            info.allocated_bytes += padding + size;
+            total_allocated_bytes_ += padding + size;
+            peak_allocated_bytes_ = std::max(total_allocated_bytes_, 
peak_allocated_bytes_);
+            DCHECK_LE(current_chunk_idx_, chunks_.size() - 1);
+            return result;
+        }
+        return nullptr;
+    }
+
     template <bool CHECK_LIMIT_FIRST>
     uint8_t* ALWAYS_INLINE allocate(int64_t size, int alignment) {
         DCHECK_GE(size, 0);
         if (UNLIKELY(size == 0)) return 
reinterpret_cast<uint8_t*>(&k_zero_length_region_);
 
         if (current_chunk_idx_ != -1) {
-            ChunkInfo& info = chunks_[current_chunk_idx_];
-            int64_t aligned_allocated_bytes =
-                    BitUtil::RoundUpToPowerOf2(info.allocated_bytes, 
alignment);
-            if (aligned_allocated_bytes + size <= info.chunk.size) {
-                // Ensure the requested alignment is respected.
-                int64_t padding = aligned_allocated_bytes - 
info.allocated_bytes;
-                uint8_t* result = info.chunk.data + aligned_allocated_bytes;
-                ASAN_UNPOISON_MEMORY_REGION(result, size);
-                DCHECK_LE(info.allocated_bytes + size, info.chunk.size);
-                info.allocated_bytes += padding + size;
-                total_allocated_bytes_ += padding + size;
-                DCHECK_LE(current_chunk_idx_, chunks_.size() - 1);
+            uint8_t* result = allocate_from_current_chunk(size, alignment);
+            if (result != nullptr) {
                 return result;
-            }
+               }
         }
 
         // If we couldn't allocate a new chunk, return nullptr. malloc() 
guarantees alignment
@@ -230,16 +258,11 @@ private:
         // guarantee alignment.
         //static_assert(
         //INITIAL_CHUNK_SIZE >= config::FLAGS_MEMORY_MAX_ALIGNMENT, "Min chunk 
size too low");
-        if (UNLIKELY(!find_chunk(size, CHECK_LIMIT_FIRST))) return nullptr;
+        if (UNLIKELY(!find_chunk(size, CHECK_LIMIT_FIRST))) {
+            return nullptr;
+        }
 
-        ChunkInfo& info = chunks_[current_chunk_idx_];
-        uint8_t* result = info.chunk.data + info.allocated_bytes;
-        ASAN_UNPOISON_MEMORY_REGION(result, size);
-        DCHECK_LE(info.allocated_bytes + size, info.chunk.size);
-        info.allocated_bytes += size;
-        total_allocated_bytes_ += size;
-        DCHECK_LE(current_chunk_idx_, chunks_.size() - 1);
-        peak_allocated_bytes_ = std::max(total_allocated_bytes_, 
peak_allocated_bytes_);
+        uint8_t* result = allocate_from_current_chunk(size, alignment);
         return result;
     }
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to