Index: compiler-rt/trunk/lib/lsan/lsan_allocator.h =================================================================== --- compiler-rt/trunk/lib/lsan/lsan_allocator.h +++ compiler-rt/trunk/lib/lsan/lsan_allocator.h @@ -99,6 +99,7 @@ void *lsan_realloc(void *p, uptr size, const StackTrace &stack); void *lsan_calloc(uptr nmemb, uptr size, const StackTrace &stack); void *lsan_valloc(uptr size, const StackTrace &stack); +void *lsan_pvalloc(uptr size, const StackTrace &stack); uptr lsan_mz_size(const void *p); } // namespace __lsan Index: compiler-rt/trunk/lib/lsan/lsan_allocator.cc =================================================================== --- compiler-rt/trunk/lib/lsan/lsan_allocator.cc +++ compiler-rt/trunk/lib/lsan/lsan_allocator.cc @@ -198,6 +198,19 @@ Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory)); } +void *lsan_pvalloc(uptr size, const StackTrace &stack) { + uptr PageSize = GetPageSizeCached(); + if (UNLIKELY(CheckForPvallocOverflow(size, PageSize))) { + errno = errno_ENOMEM; + if (AllocatorMayReturnNull()) + return nullptr; + ReportPvallocOverflow(size, &stack); + } + // pvalloc(0) should allocate one page. + size = size ? RoundUpTo(size, PageSize) : PageSize; + return SetErrnoOnNull(Allocate(stack, size, PageSize, kAlwaysClearMemory)); +} + uptr lsan_mz_size(const void *p) { return GetMallocUsableSize(p); } Index: compiler-rt/trunk/lib/lsan/lsan_interceptors.cc =================================================================== --- compiler-rt/trunk/lib/lsan/lsan_interceptors.cc +++ compiler-rt/trunk/lib/lsan/lsan_interceptors.cc @@ -165,13 +165,7 @@ INTERCEPTOR(void*, pvalloc, uptr size) { ENSURE_LSAN_INITED; GET_STACK_TRACE_MALLOC; - uptr PageSize = GetPageSizeCached(); - size = RoundUpTo(size, PageSize); - if (size == 0) { - // pvalloc(0) should allocate one page. - size = PageSize; - } - return Allocate(stack, size, GetPageSizeCached(), kAlwaysClearMemory); + return lsan_pvalloc(size, stack); } #define LSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) #else Index: compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc +++ compiler-rt/trunk/test/asan/TestCases/Linux/pvalloc-overflow.cc @@ -1,46 +0,0 @@ -// 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, android - -// REQUIRES: stable-runtime - -// Checks that pvalloc overflows are caught. If the allocator is allowed to -// return null, the errno should be set to ENOMEM. - -#include -#include -#include -#include -#include -#include - -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: {{ERROR: AddressSanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}} -// CHECK: {{#0 0x.* in .*pvalloc}} -// CHECK: {{#1 0x.* in main .*pvalloc-overflow.cc:}} -// CHECK: SUMMARY: AddressSanitizer: pvalloc-overflow Index: compiler-rt/trunk/test/msan/pvalloc.cc =================================================================== --- compiler-rt/trunk/test/msan/pvalloc.cc +++ compiler-rt/trunk/test/msan/pvalloc.cc @@ -1,46 +0,0 @@ -// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 -g %s -o %t -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t m1 2>&1 -// RUN: MSAN_OPTIONS=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s -// RUN: MSAN_OPTIONS=allocator_may_return_null=1 %run %t psm1 2>&1 - -// pvalloc is Linux only -// UNSUPPORTED: win32, freebsd, netbsd - -// Checks that pvalloc overflows are caught. If the allocator is allowed to -// return null, the errno should be set to ENOMEM. - -#include -#include -#include -#include -#include -#include - -int main(int argc, char *argv[]) { - void *p; - size_t page_size; - - assert(argc == 2); - - page_size = sysconf(_SC_PAGESIZE); - // Check that the page size is a power of two. - assert((page_size & (page_size - 1)) == 0); - - 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: {{ERROR: MemorySanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}} -// CHECK: {{#0 0x.* in .*pvalloc}} -// CHECK: SUMMARY: MemorySanitizer: pvalloc-overflow Index: compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc =================================================================== --- compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc +++ compiler-rt/trunk/test/sanitizer_common/TestCases/Linux/pvalloc-overflow.cc @@ -0,0 +1,46 @@ +// RUN: %clangxx %collect_stack_traces -O0 %s -o %t +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t m1 2>&1 | FileCheck %s +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t m1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL +// RUN: %env_tool_opts=allocator_may_return_null=0 not %run %t psm1 2>&1 | FileCheck %s +// RUN: %env_tool_opts=allocator_may_return_null=1 %run %t psm1 2>&1 | FileCheck %s --check-prefix=CHECK-NULL + +// REQUIRES: stable-runtime + +// UNSUPPORTED: android, freebsd, netbsd, tsan, ubsan + +// Checks that pvalloc overflows are caught. If the allocator is allowed to +// return null, the errno should be set to ENOMEM. + +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + assert(argc == 2); + const char *action = argv[1]; + + const size_t page_size = sysconf(_SC_PAGESIZE); + + void *p = nullptr; + if (!strcmp(action, "m1")) { + p = pvalloc((uintptr_t)-1); + } else if (!strcmp(action, "psm1")) { + p = pvalloc((uintptr_t)-(page_size - 1)); + } else { + assert(0); + } + + fprintf(stderr, "errno: %d\n", errno); + + return p != nullptr; +} + +// CHECK: {{ERROR: .*Sanitizer: pvalloc parameters overflow: size .* rounded up to system page size .* cannot be represented in type size_t}} +// CHECK: {{#0 0x.* in .*pvalloc}} +// CHECK: {{#1 0x.* in main .*pvalloc-overflow.cc:}} +// CHECK: {{SUMMARY: .*Sanitizer: pvalloc-overflow}} + +// CHECK-NULL: errno: 12