Skip to content

Commit 90418dc

Browse files
committed
[lsan] Invoke hooks on realloc
Previously lsan would not invoke hooks on reallocations. An accompanying regression test is included in sanitizer_common. This change also moves hook calls to a location where subsequent calls (via an external caller) to __sanitizer_get_allocated_size via hooks will return a valid size. This allows a faster version of __sanitizer_get_allocated_size to be implemented, which can skip checks. Test to ensure RunFreeHooks' call order will come with __sanitizer_get_allocated_size_fast Differential Revision: https://reviews.llvm.org/D151175
1 parent da60b9e commit 90418dc

File tree

2 files changed

+15
-7
lines changed

2 files changed

+15
-7
lines changed

compiler-rt/lib/lsan/lsan_allocator.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,14 @@ static void RegisterAllocation(const StackTrace &stack, void *p, uptr size) {
6565
m->stack_trace_id = StackDepotPut(stack);
6666
m->requested_size = size;
6767
atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 1, memory_order_relaxed);
68+
RunMallocHooks(p, size);
6869
}
6970

7071
static void RegisterDeallocation(void *p) {
7172
if (!p) return;
7273
ChunkMetadata *m = Metadata(p);
7374
CHECK(m);
75+
RunFreeHooks(p);
7476
atomic_store(reinterpret_cast<atomic_uint8_t *>(m), 0, memory_order_relaxed);
7577
}
7678

@@ -104,7 +106,6 @@ void *Allocate(const StackTrace &stack, uptr size, uptr alignment,
104106
if (cleared && allocator.FromPrimary(p))
105107
memset(p, 0, size);
106108
RegisterAllocation(stack, p, size);
107-
RunMallocHooks(p, size);
108109
return p;
109110
}
110111

@@ -119,7 +120,6 @@ static void *Calloc(uptr nmemb, uptr size, const StackTrace &stack) {
119120
}
120121

121122
void Deallocate(void *p) {
122-
RunFreeHooks(p);
123123
RegisterDeallocation(p);
124124
allocator.Deallocate(GetAllocatorCache(), p);
125125
}

compiler-rt/test/sanitizer_common/TestCases/malloc_hook.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const volatile void *global_ptr;
2121
// Note: avoid calling functions that allocate memory in malloc/free
2222
// to avoid infinite recursion.
2323
void __sanitizer_malloc_hook(const volatile void *ptr, size_t sz) {
24-
if (__sanitizer_get_ownership(ptr) && sz == 4) {
24+
if (__sanitizer_get_ownership(ptr) && sz == sizeof(int)) {
2525
WRITE("MallocHook\n");
2626
global_ptr = ptr;
2727
}
@@ -42,7 +42,7 @@ void FreeHook2(const volatile void *ptr) { WRITE("FH2\n"); }
4242
// TLS shadow for function parameters before calling operator
4343
// new and, eventually, user-provided hook.
4444
__attribute__((noinline)) void allocate(int *unused1, int *unused2) {
45-
x = new int;
45+
x = reinterpret_cast<int *>(malloc(sizeof(int)));
4646
}
4747

4848
int main() {
@@ -57,9 +57,17 @@ int main() {
5757
if (global_ptr != (void*)x) {
5858
_exit(1);
5959
}
60-
*x = 0;
61-
delete x;
62-
// CHECK: FreeHook
60+
61+
// Check that realloc invokes hooks
62+
// We realloc to 128 here to avoid potential oversizing by allocators
63+
// making this a no-op.
64+
x = reinterpret_cast<int *>(realloc((int *)x, sizeof(int) * 128));
65+
// CHECK-DAG: FreeHook{{[[:space:]].*}}FH1{{[[:space:]].*}}FH2
66+
// CHECK-DAG: MH1{{[[:space:]].*}}MH2
67+
68+
x[0] = 0;
69+
x[127] = -1;
70+
free((void *)x);
6371
// CHECK: FH1
6472
// CHECK: FH2
6573
return 0;

0 commit comments

Comments
 (0)