-
Notifications
You must be signed in to change notification settings - Fork 11.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ASan][libc++] Annotating std::deque with all allocators
This patch is part of our efforts to support container annotations with (almost) every allocator. Annotating std::deque with default allocator is implemented in D132092. Support in ASan API exests since rG1c5ad6d2c01294a0decde43a88e9c27d7437d157. The motivation for a research and those changes was a bug, found by Trail of Bits, in a real code where an out-of-bounds read could happen as two strings were compared via a `std::equals` function that took `iter1_begin`, `iter1_end`, `iter2_begin` iterators (with a custom comparison function). When object `iter1` was longer than `iter2`, read out-of-bounds on `iter2` could happen. Container sanitization would detect it. If you have any questions, please email: - advenam.tacet@trailofbits.com - disconnect3d@trailofbits.com Reviewed By: #libc, ldionne Differential Revision: https://reviews.llvm.org/D146815
- Loading branch information
Advenam Tacet
committed
Jul 20, 2023
1 parent
d16115d
commit 0a35ac6
Showing
3 changed files
with
93 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
libcxx/test/libcxx/containers/sequences/deque/asan_turning_off.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// UNSUPPORTED: c++03 | ||
|
||
// <deque> | ||
|
||
// Test based on: https://bugs.chromium.org/p/chromium/issues/detail?id=1419798#c5 | ||
// Some allocators during deallocation may not call destructors and just reuse memory. | ||
// In those situations, one may want to deactivate annotations for a specific allocator. | ||
// It's possible with __asan_annotate_container_with_allocator template class. | ||
// This test confirms that those allocators work after turning off annotations. | ||
|
||
#include <cassert> | ||
#include <deque> | ||
#include <new> | ||
|
||
struct reuse_allocator { | ||
static size_t const N = 100; | ||
reuse_allocator() { | ||
for (size_t i = 0; i < N; ++i) | ||
__buffers[i] = new char[8 * 1024]; | ||
} | ||
~reuse_allocator() { | ||
for (size_t i = 0; i < N; ++i) | ||
delete[] (char*)__buffers[i]; | ||
} | ||
void* alloc() { | ||
assert(__next_id < N); | ||
return __buffers[__next_id++]; | ||
} | ||
void reset() { __next_id = 0; } | ||
void* __buffers[N]; | ||
size_t __next_id = 0; | ||
} reuse_buffers; | ||
|
||
template <typename T> | ||
struct user_allocator { | ||
using value_type = T; | ||
user_allocator() = default; | ||
template <class U> | ||
user_allocator(user_allocator<U>) {} | ||
friend bool operator==(user_allocator, user_allocator) { return true; } | ||
friend bool operator!=(user_allocator x, user_allocator y) { return !(x == y); } | ||
|
||
T* allocate(size_t) { return (T*)reuse_buffers.alloc(); } | ||
void deallocate(T*, size_t) noexcept {} | ||
}; | ||
|
||
#ifdef _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS | ||
template <class T> | ||
struct std::__asan_annotate_container_with_allocator<user_allocator<T>> : false_type {}; | ||
#endif | ||
|
||
int main(int, char**) { | ||
using D = std::deque<int, user_allocator<int>>; | ||
|
||
{ | ||
D* d = new (reuse_buffers.alloc()) D(); | ||
for (int i = 0; i < 100; i++) | ||
d->push_back(i); | ||
} | ||
reuse_buffers.reset(); | ||
{ | ||
D d; | ||
for (int i = 0; i < 1000; i++) | ||
d.push_back(i); | ||
} | ||
|
||
return 0; | ||
} |