summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asan/asan_allocator.cc4
-rw-r--r--test/asan/TestCases/Linux/pvalloc-overflow.cc41
2 files changed, 45 insertions, 0 deletions
diff --git a/lib/asan/asan_allocator.cc b/lib/asan/asan_allocator.cc
index 92963ddfc..c98f9a89c 100644
--- a/lib/asan/asan_allocator.cc
+++ b/lib/asan/asan_allocator.cc
@@ -839,6 +839,10 @@ void *asan_valloc(uptr size, BufferedStackTrace *stack) {
void *asan_pvalloc(uptr size, BufferedStackTrace *stack) {
uptr PageSize = GetPageSizeCached();
+ if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) {
+ errno = errno_ENOMEM;
+ return AsanAllocator::FailureHandler::OnBadRequest();
+ }
// pvalloc(0) should allocate one page.
size = size ? RoundUpTo(size, PageSize) : PageSize;
return SetErrnoOnNull(
diff --git a/test/asan/TestCases/Linux/pvalloc-overflow.cc b/test/asan/TestCases/Linux/pvalloc-overflow.cc
new file mode 100644
index 000000000..80a2b9ce8
--- /dev/null
+++ b/test/asan/TestCases/Linux/pvalloc-overflow.cc
@@ -0,0 +1,41 @@
+// RUN: %clangxx_asan %s -o %t
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1
+// RUN: ASAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s
+// RUN: ASAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1
+
+// UNSUPPORTED: freebsd
+
+// Checks that pvalloc overflows are caught. If the allocator is allowed to
+// return null, the errno should be set to ENOMEM.
+
+#include <assert.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[]) {
+ void *p;
+ size_t page_size;
+
+ assert(argc == 2);
+
+ page_size = sysconf(_SC_PAGESIZE);
+
+ if (!strcmp(argv[1], "m1")) {
+ p = pvalloc((uintptr_t)-1);
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+ if (!strcmp(argv[1], "psm1")) {
+ p = pvalloc((uintptr_t)-(page_size - 1));
+ assert(!p);
+ assert(errno == ENOMEM);
+ }
+
+ return 0;
+}
+
+// CHECK: AddressSanitizer's allocator is terminating the process