[compiler-rt] [compiler-rt][asan] _aligned_malloc/_aligned_free interception. (PR #82049)

David CARLIER via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 4 12:09:45 PST 2024


https://github.com/devnexen updated https://github.com/llvm/llvm-project/pull/82049

>From c8cec9c0c2828ffa6d376dfc595993196718c8cf Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Fri, 16 Feb 2024 22:08:25 +0000
Subject: [PATCH 1/2] [compiler-rt][asan] _aligned_malloc/_aligned_free
 interception.

---
 compiler-rt/lib/asan/asan_malloc_win.cpp      | 20 +++++++++++++++++++
 .../asan/TestCases/Windows/aligned_alloc.cpp  | 20 +++++++++++++++++++
 2 files changed, 40 insertions(+)
 create mode 100644 compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp

diff --git a/compiler-rt/lib/asan/asan_malloc_win.cpp b/compiler-rt/lib/asan/asan_malloc_win.cpp
index 3278f072198769..213eb6587b52bd 100644
--- a/compiler-rt/lib/asan/asan_malloc_win.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_win.cpp
@@ -142,6 +142,26 @@ __declspec(noinline) void *_recalloc_base(void *p, size_t n, size_t elem_size) {
   return _recalloc(p, n, elem_size);
 }
 
+__declspec(noinline) void *_aligned_malloc(size_t alignment, size_t size) {
+  GET_STACK_TRACE_MALLOC;
+  return asan_aligned_alloc(alignment, size, &stack);
+}
+
+__declspec(noinline) void *_aligned_realloc(void *p, size_t alignment,
+                                            size_t size) {
+  GET_STACK_TRACE_MALLOC;
+  void *n = asan_aligned_alloc(alignment, size, &stack);
+  if (n) {
+    size_t osize = _msize(p);
+    REAL(memcpy)(n, p, Min<size_t>(osize, size));
+    free(p);
+  }
+
+  return n;
+}
+
+__declspec(noinline) void *_aligned_free(void *p) { free(p); }
+
 __declspec(noinline) void *_expand(void *memblock, size_t size) {
   // _expand is used in realloc-like functions to resize the buffer if possible.
   // We don't want memory to stand still while resizing buffers, so return 0.
diff --git a/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp b/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp
new file mode 100644
index 00000000000000..569e3616354015
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cl_asan %Od %s %Fe%t
+// RUN: %run %t
+
+#include <windows.h>
+
+#define CHECK_ALIGNED(ptr, alignment)                                          \
+  do {                                                                         \
+    if (((uintptr_t)(ptr) % (alignment)) != 0)                                 \
+      return __LINE__;                                                         \
+  } while (0)
+
+int main(void) {
+  char *p = reinterpret_cast<char *>(_aligned_malloc(16, 8);
+  CHECK_ALIGNED(p, 8);
+  char *n = reinterpret_cast<char *>(_aligned_realloc(32, 16));
+  CHECK_ALIGNED(n, 16);
+  _aligned_free(n);
+
+  return 0;
+}

>From 14bc9fda663612956c6a3b191a6868393e7379e7 Mon Sep 17 00:00:00 2001
From: David Carlier <devnexen at gmail.com>
Date: Mon, 4 Nov 2024 20:09:30 +0000
Subject: [PATCH 2/2] changes from feedback

---
 compiler-rt/lib/asan/asan_malloc_win.cpp      | 19 +++++++++++++------
 .../asan/TestCases/Windows/aligned_alloc.cpp  |  7 ++++++-
 2 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_malloc_win.cpp b/compiler-rt/lib/asan/asan_malloc_win.cpp
index 213eb6587b52bd..ce5d40b7fbd097 100644
--- a/compiler-rt/lib/asan/asan_malloc_win.cpp
+++ b/compiler-rt/lib/asan/asan_malloc_win.cpp
@@ -142,13 +142,13 @@ __declspec(noinline) void *_recalloc_base(void *p, size_t n, size_t elem_size) {
   return _recalloc(p, n, elem_size);
 }
 
-__declspec(noinline) void *_aligned_malloc(size_t alignment, size_t size) {
+__declspec(noinline) void *_aligned_malloc(size_t size, size_t alignment) {
   GET_STACK_TRACE_MALLOC;
   return asan_aligned_alloc(alignment, size, &stack);
 }
 
-__declspec(noinline) void *_aligned_realloc(void *p, size_t alignment,
-                                            size_t size) {
+__declspec(noinline) void *_aligned_realloc(void *p, size_t size,
+                                            size_t alignment) {
   GET_STACK_TRACE_MALLOC;
   void *n = asan_aligned_alloc(alignment, size, &stack);
   if (n) {
@@ -162,6 +162,12 @@ __declspec(noinline) void *_aligned_realloc(void *p, size_t alignment,
 
 __declspec(noinline) void *_aligned_free(void *p) { free(p); }
 
+__declspec(noinline) size_t _aligned_msize(void *p) {
+  GET_CURRENT_PC_BP_SP;
+
+  return asan_malloc_usable_size(p, pc, bp);
+}
+
 __declspec(noinline) void *_expand(void *memblock, size_t size) {
   // _expand is used in realloc-like functions to resize the buffer if possible.
   // We don't want memory to stand still while resizing buffers, so return 0.
@@ -193,9 +199,6 @@ __declspec(dllexport) void *__cdecl __asan_recalloc(void *const ptr,
   return _recalloc(ptr, nmemb, size);
 }
 
-// TODO(timurrrr): Might want to add support for _aligned_* allocation
-// functions to detect a bit more bugs.  Those functions seem to wrap malloc().
-
 int _CrtDbgReport(int, const char*, int,
                   const char*, const char*, ...) {
   ShowStatsAndAbort();
@@ -515,6 +518,10 @@ void ReplaceSystemMalloc() {
   TryToOverrideFunction("_msize_base", (uptr)_msize);
   TryToOverrideFunction("_expand", (uptr)_expand);
   TryToOverrideFunction("_expand_base", (uptr)_expand);
+  TryToOverrideFunction("_aligned_malloc", (uptr)_aligned_malloc);
+  TryToOverrideFunction("_aligned_realloc", (uptr)_aligned_realloc);
+  TryToOverrideFunction("_aligned_free", (uptr)_aligned_free);
+  TryToOverrideFunction("_aligned_msize", (uptr)_aligned_msize);
 
   if (flags()->windows_hook_rtl_allocators) {
     ASAN_INTERCEPT_FUNC(HeapSize);
diff --git a/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp b/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp
index 569e3616354015..540d93324f47a1 100644
--- a/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/aligned_alloc.cpp
@@ -10,11 +10,16 @@
   } while (0)
 
 int main(void) {
-  char *p = reinterpret_cast<char *>(_aligned_malloc(16, 8);
+  char *p = reinterpret_cast<char *>(_aligned_malloc(16, 8));
   CHECK_ALIGNED(p, 8);
   char *n = reinterpret_cast<char *>(_aligned_realloc(32, 16));
   CHECK_ALIGNED(n, 16);
   _aligned_free(n);
+  p = reinterpret_cast<char *>(_aligned_malloc(128, 8));
+  CHECK_ALIGNED(p, 8);
+  p[-1] = 'a';
+// CHECK: AddressSanitizer: heap-buffer-overflow on address [[ADDR:0x[0-9a-f]+]]
+// CHECK: WRITE of size 1 at [[ADDR]] thread T0
 
   return 0;
 }



More information about the llvm-commits mailing list