summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Shlyapnikov <alekseys@google.com>2018-06-08 20:40:35 +0000
committerAlex Shlyapnikov <alekseys@google.com>2018-06-08 20:40:35 +0000
commit77b27c99d38c3a0905272ea8a2b133b6c77b300c (patch)
tree4d95f18732d07c339f33b6c0074621442cd44478
parent8c252bbd0b5829284775ce609670a8f3de464a2c (diff)
[Sanitizers] Check alignment != 0 for aligned_alloc and posix_memalign
Summary: Move the corresponding tests to the common folder (as all of the sanitizer allocators will support this feature soon) and add the checks specific to aligned_alloc to ASan and LSan allocators. Reviewers: vitalybuka Subscribers: srhines, kubamracek, delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D47924 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@334316 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_allocator.cc11
-rw-r--r--lib/asan/asan_allocator.h1
-rw-r--r--lib/asan/asan_errors.cc22
-rw-r--r--lib/asan/asan_errors.h16
-rw-r--r--lib/asan/asan_malloc_linux.cc2
-rw-r--r--lib/asan/asan_report.cc8
-rw-r--r--lib/asan/asan_report.h2
-rw-r--r--lib/lsan/lsan_allocator.cc10
-rw-r--r--lib/lsan/lsan_allocator.h1
-rw-r--r--lib/lsan/lsan_interceptors.cc2
-rw-r--r--lib/sanitizer_common/sanitizer_allocator_checks.h8
-rw-r--r--test/asan/TestCases/Linux/aligned_alloc-alignment.cc25
-rw-r--r--test/asan/TestCases/Posix/posix_memalign-alignment.cc22
-rw-r--r--test/lsan/TestCases/Linux/aligned_alloc-alignment.cc25
-rw-r--r--test/lsan/TestCases/Posix/posix_memalign-alignment.cc22
-rw-r--r--test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc32
-rw-r--r--test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc31
17 files changed, 141 insertions, 99 deletions
diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc
index b8f7eb574..c0fad4fa0 100644
--- a/lib/asan/asan_allocator.cc
+++ b/lib/asan/asan_allocator.cc
@@ -925,6 +925,17 @@ void *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
instance.Allocate(size, alignment, stack, alloc_type, true));
}
+void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, stack);
+ }
+ return SetErrnoOnNull(
+ instance.Allocate(size, alignment, stack, FROM_MALLOC, true));
+}
+
int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
BufferedStackTrace *stack) {
if (UNLIKELY(!CheckPosixMemalignAlignment(alignment))) {
diff --git a/lib/asan/asan_allocator.h b/lib/asan/asan_allocator.h
index 1f1a71294..93d6f29c5 100644
--- a/lib/asan/asan_allocator.h
+++ b/lib/asan/asan_allocator.h
@@ -208,6 +208,7 @@ void *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
void *asan_valloc(uptr size, BufferedStackTrace *stack);
void *asan_pvalloc(uptr size, BufferedStackTrace *stack);
+void *asan_aligned_alloc(uptr alignment, uptr size, BufferedStackTrace *stack);
int asan_posix_memalign(void **memptr, uptr alignment, uptr size,
BufferedStackTrace *stack);
uptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp);
diff --git a/lib/asan/asan_errors.cc b/lib/asan/asan_errors.cc
index bd007e5c5..abbb8e6ce 100644
--- a/lib/asan/asan_errors.cc
+++ b/lib/asan/asan_errors.cc
@@ -216,6 +216,28 @@ void ErrorInvalidAllocationAlignment::Print() {
ReportErrorSummary(scariness.GetDescription(), stack);
}
+void ErrorInvalidAlignedAllocAlignment::Print() {
+ Decorator d;
+ Printf("%s", d.Warning());
+ char tname[128];
+#if SANITIZER_POSIX
+ Report("ERROR: AddressSanitizer: invalid alignment requested in "
+ "aligned_alloc: %zd, alignment must be a power of two and the "
+ "requested size 0x%zx must be a multiple of alignment "
+ "(thread T%d%s)\n", alignment, size, tid,
+ ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+#else
+ Report("ERROR: AddressSanitizer: invalid alignment requested in "
+ "aligned_alloc: %zd, the requested size 0x%zx must be a multiple of "
+ "alignment (thread T%d%s)\n", alignment, size, tid,
+ ThreadNameWithParenthesis(tid, tname, sizeof(tname)));
+#endif
+ Printf("%s", d.Default());
+ stack->Print();
+ PrintHintAllocatorCannotReturnNull("ASAN_OPTIONS");
+ ReportErrorSummary(scariness.GetDescription(), stack);
+}
+
void ErrorInvalidPosixMemalignAlignment::Print() {
Decorator d;
Printf("%s", d.Warning());
diff --git a/lib/asan/asan_errors.h b/lib/asan/asan_errors.h
index da721e2e1..512d2537b 100644
--- a/lib/asan/asan_errors.h
+++ b/lib/asan/asan_errors.h
@@ -190,6 +190,21 @@ struct ErrorInvalidAllocationAlignment : ErrorBase {
void Print();
};
+struct ErrorInvalidAlignedAllocAlignment : ErrorBase {
+ const BufferedStackTrace *stack;
+ uptr size;
+ uptr alignment;
+
+ ErrorInvalidAlignedAllocAlignment() = default; // (*)
+ ErrorInvalidAlignedAllocAlignment(u32 tid, BufferedStackTrace *stack_,
+ uptr size_, uptr alignment_)
+ : ErrorBase(tid, 10, "invalid-aligned-alloc-alignment"),
+ stack(stack_),
+ size(size_),
+ alignment(alignment_) {}
+ void Print();
+};
+
struct ErrorInvalidPosixMemalignAlignment : ErrorBase {
const BufferedStackTrace *stack;
uptr alignment;
@@ -360,6 +375,7 @@ struct ErrorGeneric : ErrorBase {
macro(CallocOverflow) \
macro(PvallocOverflow) \
macro(InvalidAllocationAlignment) \
+ macro(InvalidAlignedAllocAlignment) \
macro(InvalidPosixMemalignAlignment) \
macro(AllocationSizeTooBig) \
macro(RssLimitExceeded) \
diff --git a/lib/asan/asan_malloc_linux.cc b/lib/asan/asan_malloc_linux.cc
index 35b034e6c..5efed5d4c 100644
--- a/lib/asan/asan_malloc_linux.cc
+++ b/lib/asan/asan_malloc_linux.cc
@@ -158,7 +158,7 @@ INTERCEPTOR(void*, __libc_memalign, uptr boundary, uptr size) {
#if SANITIZER_INTERCEPT_ALIGNED_ALLOC
INTERCEPTOR(void*, aligned_alloc, uptr boundary, uptr size) {
GET_STACK_TRACE_MALLOC;
- return asan_memalign(boundary, size, &stack, FROM_MALLOC);
+ return asan_aligned_alloc(boundary, size, &stack);
}
#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index 1801738ff..18daace39 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -278,6 +278,14 @@ void ReportInvalidAllocationAlignment(uptr alignment,
in_report.ReportError(error);
}
+void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ BufferedStackTrace *stack) {
+ ScopedInErrorReport in_report(/*fatal*/ true);
+ ErrorInvalidAlignedAllocAlignment error(GetCurrentTidOrInvalid(), stack,
+ size, alignment);
+ in_report.ReportError(error);
+}
+
void ReportInvalidPosixMemalignAlignment(uptr alignment,
BufferedStackTrace *stack) {
ScopedInErrorReport in_report(/*fatal*/ true);
diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h
index e484ca90b..f7153d481 100644
--- a/lib/asan/asan_report.h
+++ b/lib/asan/asan_report.h
@@ -62,6 +62,8 @@ void ReportCallocOverflow(uptr count, uptr size, BufferedStackTrace *stack);
void ReportPvallocOverflow(uptr size, BufferedStackTrace *stack);
void ReportInvalidAllocationAlignment(uptr alignment,
BufferedStackTrace *stack);
+void ReportInvalidAlignedAllocAlignment(uptr size, uptr alignment,
+ BufferedStackTrace *stack);
void ReportInvalidPosixMemalignAlignment(uptr alignment,
BufferedStackTrace *stack);
void ReportAllocationSizeTooBig(uptr user_size, uptr total_size, uptr max_size,
diff --git a/lib/lsan/lsan_allocator.cc b/lib/lsan/lsan_allocator.cc
index 0aa6db63f..f959a3de0 100644
--- a/lib/lsan/lsan_allocator.cc
+++ b/lib/lsan/lsan_allocator.cc
@@ -157,6 +157,16 @@ int lsan_posix_memalign(void **memptr, uptr alignment, uptr size,
return 0;
}
+void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack) {
+ if (UNLIKELY(!CheckAlignedAllocAlignmentAndSize(alignment, size))) {
+ errno = errno_EINVAL;
+ if (AllocatorMayReturnNull())
+ return nullptr;
+ ReportInvalidAlignedAllocAlignment(size, alignment, &stack);
+ }
+ return SetErrnoOnNull(Allocate(stack, size, alignment, kAlwaysClearMemory));
+}
+
void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack) {
if (UNLIKELY(!IsPowerOfTwo(alignment))) {
errno = errno_EINVAL;
diff --git a/lib/lsan/lsan_allocator.h b/lib/lsan/lsan_allocator.h
index eebfc8b1a..169fcc442 100644
--- a/lib/lsan/lsan_allocator.h
+++ b/lib/lsan/lsan_allocator.h
@@ -92,6 +92,7 @@ AllocatorCache *GetAllocatorCache();
int lsan_posix_memalign(void **memptr, uptr alignment, uptr size,
const StackTrace &stack);
+void *lsan_aligned_alloc(uptr alignment, uptr size, const StackTrace &stack);
void *lsan_memalign(uptr alignment, uptr size, const StackTrace &stack);
void *lsan_malloc(uptr size, const StackTrace &stack);
void lsan_free(void *p);
diff --git a/lib/lsan/lsan_interceptors.cc b/lib/lsan/lsan_interceptors.cc
index b076d11de..e60b1ab7c 100644
--- a/lib/lsan/lsan_interceptors.cc
+++ b/lib/lsan/lsan_interceptors.cc
@@ -122,7 +122,7 @@ INTERCEPTOR(void *, __libc_memalign, uptr alignment, uptr size) {
INTERCEPTOR(void*, aligned_alloc, uptr alignment, uptr size) {
ENSURE_LSAN_INITED;
GET_STACK_TRACE_MALLOC;
- return lsan_memalign(alignment, size, stack);
+ return lsan_aligned_alloc(alignment, size, stack);
}
#define LSAN_MAYBE_INTERCEPT_ALIGNED_ALLOC INTERCEPT_FUNCTION(aligned_alloc)
#else
diff --git a/lib/sanitizer_common/sanitizer_allocator_checks.h b/lib/sanitizer_common/sanitizer_allocator_checks.h
index b61a8b2eb..61bd26e68 100644
--- a/lib/sanitizer_common/sanitizer_allocator_checks.h
+++ b/lib/sanitizer_common/sanitizer_allocator_checks.h
@@ -44,16 +44,18 @@ INLINE void *SetErrnoOnNull(void *ptr) {
// of alignment.
INLINE bool CheckAlignedAllocAlignmentAndSize(uptr alignment, uptr size) {
#if SANITIZER_POSIX
- return IsPowerOfTwo(alignment) && (size & (alignment - 1)) == 0;
+ return alignment != 0 && IsPowerOfTwo(alignment) &&
+ (size & (alignment - 1)) == 0;
#else
- return size % alignment == 0;
+ return alignment != 0 && size % alignment == 0;
#endif
}
// Checks posix_memalign() parameters, verifies that alignment is a power of two
// and a multiple of sizeof(void *).
INLINE bool CheckPosixMemalignAlignment(uptr alignment) {
- return IsPowerOfTwo(alignment) && (alignment % sizeof(void *)) == 0; // NOLINT
+ return alignment != 0 && IsPowerOfTwo(alignment) &&
+ (alignment % sizeof(void *)) == 0; // NOLINT
}
// Returns true if calloc(size, n) call overflows on size*n calculation.
diff --git a/test/asan/TestCases/Linux/aligned_alloc-alignment.cc b/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
deleted file mode 100644
index 10ce95fcd..000000000
--- a/test/asan/TestCases/Linux/aligned_alloc-alignment.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-
-// UNSUPPORTED: android
-
-// REQUIRES: stable-runtime
-
-#include <stdio.h>
-#include <stdlib.h>
-
-extern void *aligned_alloc(size_t alignment, size_t size);
-
-int main() {
- void *p = aligned_alloc(17, 100);
- // CHECK: ERROR: AddressSanitizer: invalid allocation alignment: 17
- // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}}
- // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]]
- // CHECK: SUMMARY: AddressSanitizer: invalid-allocation-alignment
-
- printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
- // CHECK-NULL: pointer after failed aligned_alloc: 0
-
- return 0;
-}
diff --git a/test/asan/TestCases/Posix/posix_memalign-alignment.cc b/test/asan/TestCases/Posix/posix_memalign-alignment.cc
deleted file mode 100644
index 1391292d2..000000000
--- a/test/asan/TestCases/Posix/posix_memalign-alignment.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %clangxx_asan -O0 %s -o %t
-// RUN: %env_asan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_asan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-
-// REQUIRES: stable-runtime
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main() {
- void *p = reinterpret_cast<void*>(42);
- int res = posix_memalign(&p, 17, 100);
- // CHECK: ERROR: AddressSanitizer: invalid alignment requested in posix_memalign: 17
- // CHECK: {{#0 0x.* in .*posix_memalign}}
- // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]]
- // CHECK: SUMMARY: AddressSanitizer: invalid-posix-memalign-alignment
-
- printf("pointer after failed posix_memalign: %zd\n", (size_t)p);
- // CHECK-NULL: pointer after failed posix_memalign: 42
-
- return 0;
-}
diff --git a/test/lsan/TestCases/Linux/aligned_alloc-alignment.cc b/test/lsan/TestCases/Linux/aligned_alloc-alignment.cc
deleted file mode 100644
index 370691d58..000000000
--- a/test/lsan/TestCases/Linux/aligned_alloc-alignment.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN: %clangxx_lsan -O0 %s -o %t
-// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-
-// UNSUPPORTED: android
-
-// REQUIRES: stable-runtime
-
-#include <stdio.h>
-#include <stdlib.h>
-
-extern void *aligned_alloc(size_t alignment, size_t size);
-
-int main() {
- void *p = aligned_alloc(17, 100);
- // CHECK: {{ERROR: .*Sanitizer: invalid allocation alignment: 17}}
- // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}}
- // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-3]]
- // CHECK: {{SUMMARY: .*Sanitizer: invalid-allocation-alignment}}
-
- printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
- // CHECK-NULL: pointer after failed aligned_alloc: 0
-
- return 0;
-}
diff --git a/test/lsan/TestCases/Posix/posix_memalign-alignment.cc b/test/lsan/TestCases/Posix/posix_memalign-alignment.cc
deleted file mode 100644
index 1b9b14ebe..000000000
--- a/test/lsan/TestCases/Posix/posix_memalign-alignment.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// RUN: %clangxx_lsan -O0 %s -o %t
-// RUN: %env_lsan_opts=allocator_may_return_null=0 not %run %t 2>&1 | FileCheck %s
-// RUN: %env_lsan_opts=allocator_may_return_null=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
-
-// REQUIRES: stable-runtime
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main() {
- void *p = reinterpret_cast<void*>(42);
- int res = posix_memalign(&p, 17, 100);
- // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in posix_memalign: 17}}
- // CHECK: {{#0 0x.* in .*posix_memalign}}
- // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]]
- // CHECK: {{SUMMARY: .*Sanitizer: invalid-posix-memalign-alignment}}
-
- printf("pointer after failed posix_memalign: %zd\n", (size_t)p);
- // CHECK-NULL: pointer after failed posix_memalign: 42
-
- return 0;
-}
diff --git a/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc b/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc
new file mode 100644
index 000000000..67b66f1e1
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Linux/aligned_alloc-alignment.cc
@@ -0,0 +1,32 @@
+// RUN: %clangxx -O0 %s -o %t
+// RUN: %tool_options=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s
+// RUN: %tool_options=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s
+// RUN: %tool_options=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+// RUN: %tool_options=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+// UNSUPPORTED: android, msan, tsan, ubsan
+
+// REQUIRES: stable-runtime
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+extern void *aligned_alloc(size_t alignment, size_t size);
+
+int main(int argc, char **argv) {
+ assert(argc == 2);
+ const int alignment = atoi(argv[1]);
+
+ void *p = aligned_alloc(alignment, 100);
+ // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in aligned_alloc}}
+ // Handle a case when aligned_alloc is aliased by memalign.
+ // CHECK: {{#0 0x.* in .*}}{{aligned_alloc|memalign}}
+ // CHECK: {{#1 0x.* in main .*aligned_alloc-alignment.cc:}}[[@LINE-4]]
+ // CHECK: {{SUMMARY: .*Sanitizer: invalid-aligned-alloc-alignment}}
+
+ printf("pointer after failed aligned_alloc: %zd\n", (size_t)p);
+ // CHECK-NULL: pointer after failed aligned_alloc: 0
+
+ return 0;
+}
diff --git a/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc b/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc
new file mode 100644
index 000000000..457855d44
--- /dev/null
+++ b/test/sanitizer_common/TestCases/Posix/posix_memalign-alignment.cc
@@ -0,0 +1,31 @@
+// RUN: %clangxx -O0 %s -o %t
+// RUN: %tool_options=allocator_may_return_null=0 not %run %t 17 2>&1 | FileCheck %s
+// RUN: %tool_options=allocator_may_return_null=0 not %run %t 0 2>&1 | FileCheck %s
+// RUN: %tool_options=allocator_may_return_null=1 %run %t 17 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+// RUN: %tool_options=allocator_may_return_null=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-NULL
+
+// REQUIRES: stable-runtime
+
+// UNSUPPORTED: msan, tsan, ubsan
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char **argv) {
+ assert(argc == 2);
+ const int alignment = atoi(argv[1]);
+
+ void *p = reinterpret_cast<void*>(42);
+
+ int res = posix_memalign(&p, alignment, 100);
+ // CHECK: {{ERROR: .*Sanitizer: invalid alignment requested in posix_memalign}}
+ // CHECK: {{#0 0x.* in .*posix_memalign}}
+ // CHECK: {{#1 0x.* in main .*posix_memalign-alignment.cc:}}[[@LINE-3]]
+ // CHECK: {{SUMMARY: .*Sanitizer: invalid-posix-memalign-alignment}}
+
+ printf("pointer after failed posix_memalign: %zd\n", (size_t)p);
+ // CHECK-NULL: pointer after failed posix_memalign: 42
+
+ return 0;
+}