Skip to content

[asan] Use InternalMmapVectorNoCtor for error_message_buffer, reallocate if needed #77488

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 19, 2024
33 changes: 17 additions & 16 deletions compiler-rt/lib/asan/asan_report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_interface_internal.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_report_decorator.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_symbolizer.h"
Expand All @@ -32,8 +33,11 @@ namespace __asan {

// -------------------- User-specified callbacks ----------------- {{{1
static void (*error_report_callback)(const char*);
static char *error_message_buffer = nullptr;
static uptr error_message_buffer_pos = 0;
typedef InternalMmapVectorNoCtor<char, true> ErrorMessageBuffer;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typedef -> using

static ALIGNED(
alignof(ErrorMessageBuffer)) char error_message_buffer_placeholder
[sizeof(ErrorMessageBuffer)];
static ErrorMessageBuffer *error_message_buffer = nullptr;
static Mutex error_message_buf_mutex;
static const unsigned kAsanBuggyPcPoolSize = 25;
static __sanitizer::atomic_uintptr_t AsanBuggyPcPool[kAsanBuggyPcPoolSize];
Expand All @@ -42,17 +46,14 @@ void AppendToErrorMessageBuffer(const char *buffer) {
Lock l(&error_message_buf_mutex);
if (!error_message_buffer) {
error_message_buffer =
(char*)MmapOrDieQuietly(kErrorMessageBufferSize, __func__);
error_message_buffer_pos = 0;
new (error_message_buffer_placeholder) ErrorMessageBuffer();
error_message_buffer->Initialize(kErrorMessageBufferSize);
}
uptr length = internal_strlen(buffer);
RAW_CHECK(kErrorMessageBufferSize >= error_message_buffer_pos);
uptr remaining = kErrorMessageBufferSize - error_message_buffer_pos;
internal_strncpy(error_message_buffer + error_message_buffer_pos,
buffer, remaining);
error_message_buffer[kErrorMessageBufferSize - 1] = '\0';
// FIXME: reallocate the buffer instead of truncating the message.
error_message_buffer_pos += Min(remaining, length);
uptr error_message_buffer_len = error_message_buffer->size();
uptr buffer_len = internal_strlen(buffer);
error_message_buffer->resize(error_message_buffer_len + buffer_len);
internal_memcpy(error_message_buffer->data() + error_message_buffer_len,
buffer, buffer_len);
}

// ---------------------- Helper functions ----------------------- {{{1
Expand Down Expand Up @@ -158,14 +159,14 @@ class ScopedInErrorReport {

// Copy the message buffer so that we could start logging without holding a
// lock that gets acquired during printing.
InternalMmapVector<char> buffer_copy(kErrorMessageBufferSize);
InternalScopedString buffer_copy;
{
Lock l(&error_message_buf_mutex);
internal_memcpy(buffer_copy.data(),
error_message_buffer, kErrorMessageBufferSize);
error_message_buffer->push_back('\0');
buffer_copy.Append(error_message_buffer->data());
// Clear error_message_buffer so that if we find other errors
// we don't re-log this error.
error_message_buffer_pos = 0;
error_message_buffer->clear();
}

LogFullErrorReport(buffer_copy.data());
Expand Down
9 changes: 5 additions & 4 deletions compiler-rt/lib/sanitizer_common/sanitizer_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report = false);
inline void *MmapOrDieQuietly(uptr size, const char *mem_type) {
return MmapOrDie(size, mem_type, /*raw_report*/ true);
}
void UnmapOrDie(void *addr, uptr size);
void UnmapOrDie(void *addr, uptr size, bool raw_report = false);
// Behaves just like MmapOrDie, but tolerates out of memory condition, in that
// case returns nullptr.
void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
Expand Down Expand Up @@ -510,7 +510,7 @@ inline int ToLower(int c) {
// A low-level vector based on mmap. May incur a significant memory overhead for
// small vectors.
// WARNING: The current implementation supports only POD types.
template<typename T>
template <typename T, bool raw_report = false>
class InternalMmapVectorNoCtor {
public:
using value_type = T;
Expand All @@ -520,7 +520,7 @@ class InternalMmapVectorNoCtor {
data_ = 0;
reserve(initial_capacity);
}
void Destroy() { UnmapOrDie(data_, capacity_bytes_); }
void Destroy() { UnmapOrDie(data_, capacity_bytes_, raw_report); }
T &operator[](uptr i) {
CHECK_LT(i, size_);
return data_[i];
Expand Down Expand Up @@ -596,7 +596,8 @@ class InternalMmapVectorNoCtor {
CHECK_LE(size_, new_capacity);
uptr new_capacity_bytes =
RoundUpTo(new_capacity * sizeof(T), GetPageSizeCached());
T *new_data = (T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector");
T *new_data =
(T *)MmapOrDie(new_capacity_bytes, "InternalMmapVector", raw_report);
internal_memcpy(new_data, data_, size_ * sizeof(T));
UnmapOrDie(data_, capacity_bytes_);
data_ = new_data;
Expand Down
8 changes: 4 additions & 4 deletions compiler-rt/lib/sanitizer_common/sanitizer_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ void *MmapOrDie(uptr size, const char *mem_type, bool raw_report) {
return (void *)res;
}

void UnmapOrDie(void *addr, uptr size) {
void UnmapOrDie(void *addr, uptr size, bool raw_report) {
if (!addr || !size) return;
uptr res = internal_munmap(addr, size);
int reserrno;
if (UNLIKELY(internal_iserror(res, &reserrno)))
ReportMunmapFailureAndDie(addr, size, reserrno);
ReportMunmapFailureAndDie(addr, size, reserrno, raw_report);
DecreaseTotalMmap(size);
}

Expand All @@ -85,8 +85,8 @@ void *MmapAlignedOrDieOnFatalError(uptr size, uptr alignment,
CHECK(IsPowerOfTwo(size));
CHECK(IsPowerOfTwo(alignment));
uptr map_size = size + alignment;
// mmap maps entire pages and rounds up map_size needs to be a an integral
// number of pages.
// mmap maps entire pages and rounds up map_size needs to be a an integral
// number of pages.
// We need to be aware of this size for calculating end and for unmapping
// fragments before and after the alignment region.
map_size = RoundUpTo(map_size, GetPageSizeCached());
Expand Down