Skip to content

Commit 0a9366d

Browse files
committed
DISPATCH-2039 Poison the memory pool so that ASAN works better with it
TODO: * does this actually do the right thing? * is it necessary to instrument `unordered_move_stack` function? When there is a read or write to the poisoned area, the error message looks like ``` ==15792==ERROR: AddressSanitizer: use-after-poison on address 0x611000034dd8 at pc 0x7fdaa75fc713 bp 0x7fff2d0c8d80 sp 0x7fff2d0c8d78 14: WRITE of size 8 at 0x611000034dd8 thread T0 14: #0 0x7fdaa75fc712 in qd_hash_internal_remove_item /home/jdanek/repos/qpid/qpid-dispatch/cmake-build-debug-asan/../src/hash.c:131:30 14: #1 0x7fdaa75fb51d in qd_hash_free /home/jdanek/repos/qpid/qpid-dispatch/cmake-build-debug-asan/../src/hash.c:146:13 [...] ```
1 parent 6b4784e commit 0a9366d

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

src/alloc_pool.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "config.h"
2525
#include "entity.h"
2626
#include "entity_cache.h"
27+
#include "qd_asan_interface.h"
2728

2829
#include "qpid/dispatch/alloc.h"
2930
#include "qpid/dispatch/ctools.h"
@@ -347,6 +348,7 @@ void *qd_alloc(qd_alloc_type_desc_t *desc, qd_alloc_pool_t **tpool)
347348
//
348349
qd_alloc_item_t *item = pop_stack(&pool->free_list);
349350
if (item) {
351+
ASAN_UNPOISON_MEMORY_REGION(&item[1], desc->total_size);
350352
#ifdef QD_MEMORY_DEBUG
351353
item->desc = desc;
352354
item->backtrace_size = backtrace(item->backtrace, STACK_DEPTH);
@@ -404,6 +406,7 @@ void *qd_alloc(qd_alloc_type_desc_t *desc, qd_alloc_pool_t **tpool)
404406
break;
405407
}
406408
item->sequence = 0;
409+
ASAN_POISON_MEMORY_REGION(&item[1], desc->total_size);
407410
#if QD_MEMORY_STATS
408411
desc->stats->held_by_threads++;
409412
desc->stats->total_alloc_from_heap++;
@@ -414,6 +417,7 @@ void *qd_alloc(qd_alloc_type_desc_t *desc, qd_alloc_pool_t **tpool)
414417

415418
item = pop_stack(&pool->free_list);
416419
if (item) {
420+
ASAN_UNPOISON_MEMORY_REGION(&item[1], desc->total_size);
417421
#ifdef QD_MEMORY_DEBUG
418422
item->desc = desc;
419423
item->backtrace_size = backtrace(item->backtrace, STACK_DEPTH);
@@ -455,6 +459,7 @@ void qd_dealloc(qd_alloc_type_desc_t *desc, qd_alloc_pool_t **tpool, char *p)
455459
item->desc = 0;
456460
QD_MEMORY_FILL(p, QD_MEMORY_FREE, desc->total_size);
457461
#endif
462+
ASAN_POISON_MEMORY_REGION(p, desc->total_size);
458463

459464
//
460465
// If this is the thread's first pass through here, allocate the

src/qd_asan_interface.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
#ifndef __qd_asan_interface_h__
2+
#define __qd_asan_interface_h__ 1
3+
/*
4+
* Licensed to the Apache Software Foundation (ASF) under one
5+
* or more contributor license agreements. See the NOTICE file
6+
* distributed with this work for additional information
7+
* regarding copyright ownership. The ASF licenses this file
8+
* to you under the Apache License, Version 2.0 (the
9+
* "License"); you may not use this file except in compliance
10+
* with the License. You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing,
15+
* software distributed under the License is distributed on an
16+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
* KIND, either express or implied. See the License for the
18+
* specific language governing permissions and limitations
19+
* under the License.
20+
*/
21+
22+
/**
23+
* Defines the ASAN interface file if available. If not, defines stub macros.
24+
*
25+
* See #include <sanitizer/asan_interface.h> in Clang for the source.
26+
*/
27+
28+
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
29+
30+
void __asan_poison_memory_region(void const volatile *addr, size_t size);
31+
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
32+
33+
/// Marks a memory region as unaddressable.
34+
///
35+
/// \note Macro provided for convenience; defined as a no-op if ASan is not
36+
/// enabled.
37+
///
38+
/// \param addr Start of memory region.
39+
/// \param size Size of memory region.
40+
#define ASAN_POISON_MEMORY_REGION(addr, size) \
41+
__asan_poison_memory_region((addr), (size))
42+
43+
/// Marks a memory region as addressable.
44+
///
45+
/// \note Macro provided for convenience; defined as a no-op if ASan is not
46+
/// enabled.
47+
///
48+
/// \param addr Start of memory region.
49+
/// \param size Size of memory region.
50+
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
51+
__asan_unpoison_memory_region((addr), (size))
52+
53+
#else // __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
54+
55+
#define ASAN_POISON_MEMORY_REGION(addr, size) \
56+
((void)(addr), (void)(size))
57+
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
58+
((void)(addr), (void)(size))
59+
60+
#endif // __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
61+
62+
// https://github.com/google/sanitizers/wiki/AddressSanitizer#turning-off-instrumentation
63+
64+
#if defined(__clang__) || defined (__GNUC__)
65+
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
66+
#else
67+
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
68+
#endif
69+
70+
#endif // __qd_asan_interface_h__

0 commit comments

Comments
 (0)