[PATCH] D17690: [asan] Check if the memory is readable before using the AsanChunk in free() and realloc()
Filipe Cabecinhas via llvm-commits
llvm-commits at lists.llvm.org
Sun Feb 28 01:39:32 PST 2016
filcab created this revision.
filcab added reviewers: kcc, samsonov, earthdok.
filcab added a subscriber: llvm-commits.
This allows us to better diagnose free() and realloc() with a bad
pointer, instead of SIGSEGV.
http://reviews.llvm.org/D17690
Files:
lib/asan/asan_allocator.cc
test/asan/TestCases/Posix/bad-free-no-segv.cc
Index: test/asan/TestCases/Posix/bad-free-no-segv.cc
===================================================================
--- /dev/null
+++ test/asan/TestCases/Posix/bad-free-no-segv.cc
@@ -0,0 +1,31 @@
+// RUN: %clangxx_asan -O0 %s -o %t
+// RUN: not %run %t f 2>&1 | FileCheck %s
+// RUN: not %run %t r 2>&1 | FileCheck %s
+#include <assert.h>
+#include <stdlib.h>
+#include <sanitizer/asan_interface.h>
+
+// CHECK-NOT: DEADLYSIGNAL
+// CHECK: AddressSanitizer: attempting free on address which was not malloc()-ed
+int main(int argc, char **argv) {
+ // The shadow gap is mprotect()ed, so we get an address inside it and pass it
+ // along to free. reading from it should be a problem and ASan should notice
+ // it before trying to read.
+ size_t shadow_scale, shadow_offset;
+ __asan_get_shadow_mapping(&shadow_scale, &shadow_offset);
+ // We add 0x100 because asan_free subtracts sizeof(AsanChunk) to our ptr.
+ // Which means we need to make sure that the free()ed/realloc()ed pointer is
+ // also in non-addressable memory.
+ void *p = (void *)(shadow_offset + 0x1000 + (shadow_offset >> shadow_scale));
+ assert(argc == 2);
+ switch (argv[1][0]) {
+ case 'f':
+ free(p);
+ break;
+ case 'r':
+ realloc(p, 42);
+ break;
+ default:
+ assert(false);
+ }
+}
Index: lib/asan/asan_allocator.cc
===================================================================
--- lib/asan/asan_allocator.cc
+++ lib/asan/asan_allocator.cc
@@ -22,6 +22,7 @@
#include "asan_stack.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
+#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_internal_defs.h"
#include "sanitizer_common/sanitizer_list.h"
@@ -523,6 +524,8 @@
uptr chunk_beg = p - kChunkHeaderSize;
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+ if (!IsAccessibleMemoryRange((uptr)m, sizeof(AsanChunk)))
+ ReportFreeNotMalloced((uptr)ptr, stack);
if (delete_size && flags()->new_delete_type_mismatch &&
delete_size != m->UsedSize()) {
ReportNewDeleteSizeMismatch(p, delete_size, stack);
@@ -539,6 +542,8 @@
uptr p = reinterpret_cast<uptr>(old_ptr);
uptr chunk_beg = p - kChunkHeaderSize;
AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
+ if (!IsAccessibleMemoryRange((uptr)m, sizeof(AsanChunk)))
+ ReportFreeNotMalloced((uptr)old_ptr, stack);
AsanStats &thread_stats = GetCurrentThreadStats();
thread_stats.reallocs++;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D17690.49313.patch
Type: text/x-patch
Size: 2559 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160228/9bf37c48/attachment.bin>
More information about the llvm-commits
mailing list