Merge "Init functions after debug malloc succeeds."
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index aa6f5f7..568192d 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -282,6 +282,10 @@
     return g_dispatch->malloc(size);
   }
 
+  if (size == 0) {
+    size = 1;
+  }
+
   size_t real_size = size + g_debug->extra_bytes();
   if (real_size < size) {
     // Overflow.
@@ -377,6 +381,10 @@
     return g_dispatch->memalign(alignment, bytes);
   }
 
+  if (bytes == 0) {
+    bytes = 1;
+  }
+
   void* pointer;
   if (g_debug->need_header()) {
     if (bytes > Header::max_size()) {
@@ -530,8 +538,19 @@
     return g_dispatch->calloc(nmemb, bytes);
   }
 
-  size_t real_size = nmemb * bytes + g_debug->extra_bytes();
-  if (real_size < bytes || real_size < nmemb) {
+  size_t size;
+  if (__builtin_mul_overflow(nmemb, bytes, &size)) {
+    // Overflow
+    errno = ENOMEM;
+    return nullptr;
+  }
+
+  if (size == 0) {
+    size = 1;
+  }
+
+  size_t real_size;
+  if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
     // Overflow.
     errno = ENOMEM;
     return nullptr;
@@ -539,7 +558,7 @@
 
   if (g_debug->need_header()) {
     // The above check will guarantee the multiply will not overflow.
-    if (bytes * nmemb > Header::max_size()) {
+    if (size > Header::max_size()) {
       errno = ENOMEM;
       return nullptr;
     }
@@ -551,7 +570,7 @@
       return nullptr;
     }
     memset(header, 0, g_dispatch->malloc_usable_size(header));
-    return InitHeader(header, header, nmemb * bytes);
+    return InitHeader(header, header, size);
   } else {
     return g_dispatch->calloc(1, real_size);
   }
@@ -594,7 +613,7 @@
             if (g_debug->track->Contains(header)) {
               // Return just the body of the allocation if we're sure the header exists
               ctx->callback(reinterpret_cast<uintptr_t>(g_debug->GetPointer(header)),
-                  header->real_size(), ctx->arg);
+                  header->usable_size, ctx->arg);
               return;
             }
           }
diff --git a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
index 28729e8..2503981 100644
--- a/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
+++ b/libc/malloc_debug/tests/malloc_debug_unit_tests.cpp
@@ -1290,6 +1290,12 @@
   ASSERT_TRUE(pointer == nullptr);
   ASSERT_EQ(ENOMEM, errno);
 
+  const size_t size_t_bits = sizeof(size_t) * 8;
+  const size_t sqrt_size_t = 1ULL << (size_t_bits/2);
+  pointer = debug_calloc(sqrt_size_t + 1, sqrt_size_t);
+  ASSERT_TRUE(pointer == nullptr);
+  ASSERT_EQ(ENOMEM, errno);
+
   pointer = debug_realloc(nullptr, SIZE_MAX);
   ASSERT_TRUE(pointer == nullptr);
   ASSERT_EQ(ENOMEM, errno);
diff --git a/libm/Android.bp b/libm/Android.bp
index a4f6135..fb0e583 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -387,6 +387,8 @@
                 "x86/libm_reduce_pi04l.S",
                 "x86/libm_sincos_huge.S",
                 "x86/libm_tancot_huge.S",
+                "x86/lrint.S",
+                "x86/lrintf.S",
                 "x86/s_atan.S",
                 "x86/s_cbrt.S",
                 "x86/s_cos.S",
@@ -414,6 +416,8 @@
                 "upstream-freebsd/lib/msun/src/s_cos.c",
                 "upstream-freebsd/lib/msun/src/s_expm1.c",
                 "upstream-freebsd/lib/msun/src/s_log1p.c",
+                "upstream-freebsd/lib/msun/src/s_lrint.c",
+                "upstream-freebsd/lib/msun/src/s_lrintf.c",
                 "upstream-freebsd/lib/msun/src/s_sin.c",
                 "upstream-freebsd/lib/msun/src/s_tan.c",
                 "upstream-freebsd/lib/msun/src/s_tanh.c",
@@ -424,6 +428,8 @@
                     "x86/ceilf.S",
                     "x86/floor.S",
                     "x86/floorf.S",
+                    "x86/rint.S",
+                    "x86/rintf.S",
                     "x86/trunc.S",
                     "x86/truncf.S",
                 ],
@@ -432,6 +438,8 @@
                     "upstream-freebsd/lib/msun/src/s_ceilf.c",
                     "upstream-freebsd/lib/msun/src/s_floor.c",
                     "upstream-freebsd/lib/msun/src/s_floorf.c",
+                    "upstream-freebsd/lib/msun/src/s_rint.c",
+                    "upstream-freebsd/lib/msun/src/s_rintf.c",
                     "upstream-freebsd/lib/msun/src/s_trunc.c",
                     "upstream-freebsd/lib/msun/src/s_truncf.c",
                 ],
@@ -456,6 +464,8 @@
                 "x86_64/e_log.S",
                 "x86_64/e_pow.S",
                 "x86_64/e_sinh.S",
+                "x86_64/lrint.S",
+                "x86_64/lrintf.S",
                 "x86_64/s_atan.S",
                 "x86_64/s_cbrt.S",
                 "x86_64/s_cos.S",
@@ -483,6 +493,10 @@
                 "upstream-freebsd/lib/msun/src/s_cos.c",
                 "upstream-freebsd/lib/msun/src/s_expm1.c",
                 "upstream-freebsd/lib/msun/src/s_log1p.c",
+                "upstream-freebsd/lib/msun/src/s_llrint.c",
+                "upstream-freebsd/lib/msun/src/s_llrintf.c",
+                "upstream-freebsd/lib/msun/src/s_lrint.c",
+                "upstream-freebsd/lib/msun/src/s_lrintf.c",
                 "upstream-freebsd/lib/msun/src/s_sin.c",
                 "upstream-freebsd/lib/msun/src/s_tan.c",
                 "upstream-freebsd/lib/msun/src/s_tanh.c",
@@ -493,6 +507,8 @@
                     "x86_64/ceilf.S",
                     "x86_64/floor.S",
                     "x86_64/floorf.S",
+                    "x86_64/rint.S",
+                    "x86_64/rintf.S",
                     "x86_64/trunc.S",
                     "x86_64/truncf.S",
                 ],
@@ -501,6 +517,8 @@
                     "upstream-freebsd/lib/msun/src/s_ceilf.c",
                     "upstream-freebsd/lib/msun/src/s_floor.c",
                     "upstream-freebsd/lib/msun/src/s_floorf.c",
+                    "upstream-freebsd/lib/msun/src/s_rint.c",
+                    "upstream-freebsd/lib/msun/src/s_rintf.c",
                     "upstream-freebsd/lib/msun/src/s_trunc.c",
                     "upstream-freebsd/lib/msun/src/s_truncf.c",
                 ],
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index d11ea3f..aab78ad 100755
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -1347,6 +1347,9 @@
 // the wrong map with [stack]. This test verifies that when the above situation happens, the main
 // thread's stack is found correctly.
 TEST(pthread, pthread_attr_getstack_in_signal_handler) {
+  // This test is only meaningful for the main thread, so make sure we're running on it!
+  ASSERT_EQ(getpid(), syscall(__NR_gettid));
+
   const size_t sig_stack_size = 16 * 1024;
   void* sig_stack = mmap(NULL, sig_stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
                          -1, 0);
@@ -1358,6 +1361,12 @@
   stack_t oss;
   ASSERT_EQ(0, sigaltstack(&ss, &oss));
 
+  pthread_attr_t attr;
+  ASSERT_EQ(0, pthread_getattr_np(pthread_self(), &attr));
+  void* main_stack_base;
+  size_t main_stack_size;
+  ASSERT_EQ(0, pthread_attr_getstack(&attr, &main_stack_base, &main_stack_size));
+
   ScopedSignalHandler handler(SIGUSR1, getstack_signal_handler, SA_ONSTACK);
   getstack_signal_handler_arg.done = false;
   kill(getpid(), SIGUSR1);
@@ -1369,9 +1378,8 @@
             getstack_signal_handler_arg.signal_handler_sp);
 
   // Verify if the main thread's stack got in the signal handler is correct.
-  ASSERT_LE(getstack_signal_handler_arg.main_stack_base, &ss);
-  ASSERT_GE(reinterpret_cast<char*>(getstack_signal_handler_arg.main_stack_base) +
-            getstack_signal_handler_arg.main_stack_size, reinterpret_cast<void*>(&ss));
+  ASSERT_EQ(main_stack_base, getstack_signal_handler_arg.main_stack_base);
+  ASSERT_LE(main_stack_size, getstack_signal_handler_arg.main_stack_size);
 
   ASSERT_EQ(0, sigaltstack(&oss, nullptr));
   ASSERT_EQ(0, munmap(sig_stack, sig_stack_size));