Merge "Sync with OpenBSD strptime.c." into main
diff --git a/libc/bionic/getentropy.cpp b/libc/bionic/getentropy.cpp
index 11f5028..5272c34 100644
--- a/libc/bionic/getentropy.cpp
+++ b/libc/bionic/getentropy.cpp
@@ -63,11 +63,17 @@
     long count = TEMP_FAILURE_RETRY(getrandom(static_cast<char*>(buffer) + collected,
                                               buffer_size - collected, GRND_NONBLOCK));
     if (count == -1) {
+      // One of several things could have gone wrong:
       // EAGAIN: there isn't enough entropy right now.
       // ENOSYS/EINVAL: getrandom(2) or GRND_NONBLOCK isn't supported.
       // EFAULT: `buffer` is invalid.
-      // Try /dev/urandom regardless because it can't hurt,
+      // Realistically we're here because of EAGAIN,
+      // for which /dev/urandom is the solution ---
+      // it'll return low entropy randomness where getrandom() won't,
+      // but we fall back /dev/urandom for all cases because it can't hurt,
       // and we don't need to optimize the EFAULT case.
+      // See https://man7.org/linux/man-pages/man7/random.7.html for getrandom()
+      // vs /dev/random vs /dev/urandom.
       // See http://b/33059407 and http://b/67015565.
       return getentropy_urandom(buffer, buffer_size, saved_errno);
     }
diff --git a/libc/bionic/time.cpp b/libc/bionic/time.cpp
index 800395e..3b18390 100644
--- a/libc/bionic/time.cpp
+++ b/libc/bionic/time.cpp
@@ -28,6 +28,53 @@
 
 #include <time.h>
 
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+char* asctime(const tm* tm) {
+  static char buf[128];
+  return asctime_r(tm, buf);
+}
+
+char* asctime_r(const tm* tm, char* buf) {
+  if (tm == nullptr) {
+    errno = EINVAL;
+    return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
+  }
+
+  auto pick = [](unsigned n, unsigned max, const char* s) {
+    return (n < max) ? s + 3*n : "???";
+  };
+  const char* day = pick(tm->tm_wday, 7, "SunMonTueWedThuFriSat");
+  const char* mon = pick(tm->tm_mon, 12, "JanFebMarAprMayJunJulAugSepOctNovDec");
+
+  char tmp_buf[26];
+  int n = snprintf(tmp_buf, 26, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", day, mon,
+                   tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, 1900 + tm->tm_year);
+  if (n > 25) {
+    errno = EOVERFLOW;
+    return nullptr;
+  }
+  strcpy(buf, tmp_buf);
+  return buf;
+}
+
+char* ctime(const time_t* tp) {
+  static char buf[128];
+  return ctime_r(tp, buf);
+}
+
+char* ctime_r(const time_t* tp, char* buf) {
+  struct tm tm;
+  if (localtime_r(tp, &tm) == nullptr) return nullptr;
+  return asctime_r(&tm, buf);
+}
+
+double difftime(time_t t1, time_t t0) {
+  return t1 - t0;
+}
+
 int timespec_get(timespec* ts, int base) {
   return (clock_gettime(base - 1, ts) != -1) ? base : 0;
 }
diff --git a/libc/include/time.h b/libc/include/time.h
index 3d7ac57..a002244 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -141,11 +141,11 @@
 
 /**
  * [difftime(3)](https://man7.org/linux/man-pages/man3/difftime.3.html) returns
- * the difference between two times.
+ * the difference between two times, equivalent to (time1 - time0).
  *
  * Returns the difference in seconds.
  */
-double difftime(time_t __lhs, time_t __rhs);
+double difftime(time_t __time1, time_t __time0);
 
 /**
  * [mktime(3)](https://man7.org/linux/man-pages/man3/mktime.3p.html) converts
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index 408a046..fadaae3 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -25,8 +25,9 @@
     stl: "libc++_static",
 
     whole_static_libs: [
-        "libbase",
         "libasync_safe",
+        "libbase",
+        "libunwindstack_demangle",
     ],
 
     include_dirs: ["bionic/libc"],
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index c8aaa08..5129bf6 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -26,7 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <cxxabi.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <signal.h>
@@ -49,6 +48,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/thread_annotations.h>
 #include <platform/bionic/macros.h>
+#include <unwindstack/Demangle.h>
 
 #include "Config.h"
 #include "DebugData.h"
@@ -619,16 +619,9 @@
         if (frame.function_name.empty()) {
           dprintf(fd, " \"\" 0}");
         } else {
-          char* demangled_name =
-              abi::__cxa_demangle(frame.function_name.c_str(), nullptr, nullptr, nullptr);
-          const char* name;
-          if (demangled_name != nullptr) {
-            name = demangled_name;
-          } else {
-            name = frame.function_name.c_str();
-          }
-          dprintf(fd, " \"%s\" %" PRIx64 "}", name, frame.function_offset);
-          free(demangled_name);
+          dprintf(fd, " \"%s\" %" PRIx64 "}",
+                  unwindstack::DemangleNameIfNeeded(frame.function_name).c_str(),
+                  frame.function_offset);
         }
       }
       dprintf(fd, "\n");
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index 8a6ff7b..740fabe 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -26,7 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <cxxabi.h>
 #include <inttypes.h>
 #include <pthread.h>
 #include <stdint.h>
@@ -38,6 +37,7 @@
 
 #include <android-base/stringprintf.h>
 #include <unwindstack/AndroidUnwinder.h>
+#include <unwindstack/Demangle.h>
 #include <unwindstack/Unwinder.h>
 
 #include "UnwindBacktrace.h"
@@ -88,14 +88,7 @@
 
     if (!info->function_name.empty()) {
       line += " (";
-      char* demangled_name =
-          abi::__cxa_demangle(info->function_name.c_str(), nullptr, nullptr, nullptr);
-      if (demangled_name != nullptr) {
-        line += demangled_name;
-        free(demangled_name);
-      } else {
-        line += info->function_name;
-      }
+      line += unwindstack::DemangleNameIfNeeded(info->function_name);
       if (info->function_offset != 0) {
         line += "+" + std::to_string(info->function_offset);
       }
diff --git a/libc/malloc_debug/backtrace.cpp b/libc/malloc_debug/backtrace.cpp
index 6a32fca..8b58be3 100644
--- a/libc/malloc_debug/backtrace.cpp
+++ b/libc/malloc_debug/backtrace.cpp
@@ -26,7 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include <cxxabi.h>
 #include <dlfcn.h>
 #include <errno.h>
 #include <inttypes.h>
@@ -41,6 +40,8 @@
 #include "backtrace.h"
 #include "debug_log.h"
 
+#include <unwindstack/Demangle.h>
+
 #if defined(__LP64__)
 #define PAD_PTR "016" PRIxPTR
 #else
@@ -154,18 +155,10 @@
 
     char buf[1024];
     if (symbol != nullptr) {
-      char* demangled_name = abi::__cxa_demangle(symbol, nullptr, nullptr, nullptr);
-      const char* name;
-      if (demangled_name != nullptr) {
-        name = demangled_name;
-      } else {
-        name = symbol;
-      }
-      async_safe_format_buffer(buf, sizeof(buf),
-                               "          #%02zd  pc %" PAD_PTR "  %s%s (%s+%" PRIuPTR ")\n",
-                               frame_num, rel_pc, soname, offset_buf, name,
-                               frames[frame_num] - offset);
-      free(demangled_name);
+      async_safe_format_buffer(
+          buf, sizeof(buf), "          #%02zd  pc %" PAD_PTR "  %s%s (%s+%" PRIuPTR ")\n",
+          frame_num, rel_pc, soname, offset_buf, unwindstack::DemangleNameIfNeeded(symbol).c_str(),
+          frames[frame_num] - offset);
     } else {
       async_safe_format_buffer(buf, sizeof(buf), "          #%02zd  pc %" PAD_PTR "  %s%s\n",
                                frame_num, rel_pc, soname, offset_buf);
diff --git a/libc/tzcode/asctime.c b/libc/tzcode/asctime.c
deleted file mode 100644
index 4cdfd13..0000000
--- a/libc/tzcode/asctime.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/* asctime and asctime_r a la POSIX and ISO C, except pad years before 1000.  */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*
-** Avoid the temptation to punt entirely to strftime;
-** the output of strftime is supposed to be locale specific
-** whereas the output of asctime is supposed to be constant.
-*/
-
-/*LINTLIBRARY*/
-
-#include "private.h"
-#include <stdio.h>
-
-/*
-** All years associated with 32-bit time_t values are exactly four digits long;
-** some years associated with 64-bit time_t values are not.
-** Vintage programs are coded for years that are always four digits long
-** and may assume that the newline always lands in the same place.
-** For years that are less than four digits, we pad the output with
-** leading zeroes to get the newline in the traditional place.
-** The -4 ensures that we get four characters of output even if
-** we call a strftime variant that produces fewer characters for some years.
-** The ISO C and POSIX standards prohibit padding the year,
-** but many implementations pad anyway; most likely the standards are buggy.
-*/
-static char const ASCTIME_FMT[] = "%s %s%3d %.2d:%.2d:%.2d %-4s\n";
-/*
-** For years that are more than four digits we put extra spaces before the year
-** so that code trying to overwrite the newline won't end up overwriting
-** a digit within a year and truncating the year (operating on the assumption
-** that no output is better than wrong output).
-*/
-static char const ASCTIME_FMT_B[] = "%s %s%3d %.2d:%.2d:%.2d     %s\n";
-
-enum { STD_ASCTIME_BUF_SIZE = 26 };
-/*
-** Big enough for something such as
-** ??? ???-2147483648 -2147483648:-2147483648:-2147483648     -2147483648\n
-** (two three-character abbreviations, five strings denoting integers,
-** seven explicit spaces, two explicit colons, a newline,
-** and a trailing NUL byte).
-** The values above are for systems where an int is 32 bits and are provided
-** as an example; the size expression below is a bound for the system at
-** hand.
-*/
-static char buf_asctime[2*3 + 5*INT_STRLEN_MAXIMUM(int) + 7 + 2 + 1 + 1];
-
-/* A similar buffer for ctime.
-   C89 requires that they be the same buffer.
-   This requirement was removed in C99, so support it only if requested,
-   as support is more likely to lead to bugs in badly written programs.  */
-#if SUPPORT_C89
-# define buf_ctime buf_asctime
-#else
-static char buf_ctime[sizeof buf_asctime];
-#endif
-
-char *
-asctime_r(struct tm const *restrict timeptr, char *restrict buf)
-{
-	static const char	wday_name[][4] = {
-		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-	};
-	static const char	mon_name[][4] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-	};
-	register const char *	wn;
-	register const char *	mn;
-	char			year[INT_STRLEN_MAXIMUM(int) + 2];
-	char result[sizeof buf_asctime];
-
-	if (timeptr == NULL) {
-		errno = EINVAL;
-		return strcpy(buf, "??? ??? ?? ??:??:?? ????\n");
-	}
-	if (timeptr->tm_wday < 0 || timeptr->tm_wday >= DAYSPERWEEK)
-		wn = "???";
-	else	wn = wday_name[timeptr->tm_wday];
-	if (timeptr->tm_mon < 0 || timeptr->tm_mon >= MONSPERYEAR)
-		mn = "???";
-	else	mn = mon_name[timeptr->tm_mon];
-	/*
-	** Use strftime's %Y to generate the year, to avoid overflow problems
-	** when computing timeptr->tm_year + TM_YEAR_BASE.
-	** Assume that strftime is unaffected by other out-of-range members
-	** (e.g., timeptr->tm_mday) when processing "%Y".
-	*/
-	strftime(year, sizeof year, "%Y", timeptr);
-	/*
-	** We avoid using snprintf since it's not available on all systems.
-	*/
-	snprintf(result, sizeof(result), /* Android change: use snprintf. */
-		((strlen(year) <= 4) ? ASCTIME_FMT : ASCTIME_FMT_B),
-		wn, mn,
-		timeptr->tm_mday, timeptr->tm_hour,
-		timeptr->tm_min, timeptr->tm_sec,
-		year);
-	if (strlen(result) < STD_ASCTIME_BUF_SIZE
-	    || buf == buf_ctime || buf == buf_asctime)
-		return strcpy(buf, result);
-	else {
-		errno = EOVERFLOW;
-		return NULL;
-	}
-}
-
-char *
-asctime(register const struct tm *timeptr)
-{
-	return asctime_r(timeptr, buf_asctime);
-}
-
-char *
-ctime_r(const time_t *timep, char *buf)
-{
-  struct tm mytm;
-  struct tm *tmp = localtime_r(timep, &mytm);
-  return tmp ? asctime_r(tmp, buf) : NULL;
-}
-
-char *
-ctime(const time_t *timep)
-{
-  return ctime_r(timep, buf_ctime);
-}
diff --git a/libc/tzcode/difftime.c b/libc/tzcode/difftime.c
deleted file mode 100644
index ff78f03..0000000
--- a/libc/tzcode/difftime.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/* Return the difference between two timestamps.  */
-
-/*
-** This file is in the public domain, so clarified as of
-** 1996-06-05 by Arthur David Olson.
-*/
-
-/*LINTLIBRARY*/
-
-#include "private.h"	/* for time_t and TYPE_SIGNED */
-
-/* Return -X as a double.  Using this avoids casting to 'double'.  */
-static double
-dminus(double x)
-{
-  return -x;
-}
-
-double
-difftime(time_t time1, time_t time0)
-{
-	/*
-	** If double is large enough, simply convert and subtract
-	** (assuming that the larger type has more precision).
-	*/
-	if (sizeof(time_t) < sizeof(double)) {
-	  double t1 = time1, t0 = time0;
-	  return t1 - t0;
-	}
-
-	/*
-	** The difference of two unsigned values can't overflow
-	** if the minuend is greater than or equal to the subtrahend.
-	*/
-	if (!TYPE_SIGNED(time_t))
-	  return time0 <= time1 ? time1 - time0 : dminus(time0 - time1);
-
-	/* Use uintmax_t if wide enough.  */
-	if (sizeof(time_t) <= sizeof(uintmax_t)) {
-	  uintmax_t t1 = time1, t0 = time0;
-	  return time0 <= time1 ? t1 - t0 : dminus(t0 - t1);
-	}
-
-	/*
-	** Handle cases where both time1 and time0 have the same sign
-	** (meaning that their difference cannot overflow).
-	*/
-	if ((time1 < 0) == (time0 < 0))
-	  return time1 - time0;
-
-	/*
-	** The values have opposite signs and uintmax_t is too narrow.
-	** This suffers from double rounding; attempt to lessen that
-	** by using long double temporaries.
-	*/
-	{
-	  long double t1 = time1, t0 = time0;
-	  return t1 - t0;
-	}
-}
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 525dfc4..3ae010b 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -632,11 +632,19 @@
 	char *ep;
 
 	errno = 0;
+#if defined(__LP64__)
 	secs = strtoll(*buf, &ep, 10);
+#else
+	secs = strtol(*buf, &ep, 10);
+#endif
 	if (*buf == (unsigned char *)ep)
 		goto done;
 	if (secs < 0 ||
+#if defined(__LP64__)
 	    secs == LLONG_MAX && errno == ERANGE)
+#else
+	    secs == LONG_MAX && errno == ERANGE)
+#endif
 		goto done;
 	if (localtime_r(&secs, tm) == NULL)
 		goto done;
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index cf4de06..73590fa 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -484,6 +484,62 @@
   EXPECT_EQ(0, tm.tm_hour);
 }
 
+TEST(time, strptime_s) {
+  setenv("TZ", "UTC", 1);
+
+  struct tm tm;
+
+  // 0 + 1 --- trivial.
+  tm = {};
+  ASSERT_EQ('\0', *strptime("1", "%s", &tm));
+  EXPECT_EQ(70, tm.tm_year);
+  EXPECT_EQ(0, tm.tm_mon);
+  EXPECT_EQ(1, tm.tm_mday);
+  EXPECT_EQ(0, tm.tm_hour);
+  EXPECT_EQ(0, tm.tm_min);
+  EXPECT_EQ(1, tm.tm_sec);
+
+  // INT32_MAX (aka "time_t max" for ILP32).
+  tm = {};
+  ASSERT_EQ('\0', *strptime("2147483647", "%s", &tm));
+  EXPECT_EQ(138, tm.tm_year);
+  EXPECT_EQ(0, tm.tm_mon);
+  EXPECT_EQ(19, tm.tm_mday);
+  EXPECT_EQ(3, tm.tm_hour);
+  EXPECT_EQ(14, tm.tm_min);
+  EXPECT_EQ(7, tm.tm_sec);
+
+  // INT32_MAX + 1 (aka overflow for ILP32).
+  // This should be easy to detect because it'll be negative.
+  tm = {};
+#if defined(__LP64__)
+  ASSERT_EQ('\0', *strptime("2147483648", "%s", &tm));
+#else
+  ASSERT_EQ(nullptr, strptime("2147483648", "%s", &tm));
+#endif
+
+  // This wraps to 1 as an int32_t.
+  tm = {};
+#if defined(__LP64__)
+  ASSERT_EQ('\0', *strptime("4294967297", "%s", &tm));
+  EXPECT_EQ(206, tm.tm_year);
+  EXPECT_EQ(1, tm.tm_mon);
+  EXPECT_EQ(7, tm.tm_mday);
+  EXPECT_EQ(6, tm.tm_hour);
+  EXPECT_EQ(28, tm.tm_min);
+  EXPECT_EQ(17, tm.tm_sec);
+#else
+  ASSERT_EQ(nullptr, strptime("4294967297", "%s", &tm));
+#endif
+
+  // INT64_MAX (aka "time_t max" for LP64).
+  // This actually fails for LP64 too...
+  // ...but in localtime_r() because the year is too large.
+  // (Wolfram Alpha says this is 21 times the age of the universe!)
+  tm = {};
+  ASSERT_EQ(nullptr, strptime("9223372036854775807", "%s", &tm));
+}
+
 TEST(time, strptime_u) {
   setenv("TZ", "UTC", 1);
 
@@ -1197,17 +1253,63 @@
 }
 
 TEST(time, asctime) {
-  const struct tm tm = {};
+  const tm tm = {};
   ASSERT_STREQ("Sun Jan  0 00:00:00 1900\n", asctime(&tm));
 }
 
 TEST(time, asctime_r) {
-  const struct tm tm = {};
+  const tm tm = {};
   char buf[256];
   ASSERT_EQ(buf, asctime_r(&tm, buf));
   ASSERT_STREQ("Sun Jan  0 00:00:00 1900\n", buf);
 }
 
+TEST(time, asctime_nullptr) {
+  tm* smuggled_null = nullptr;
+  char buf[256];
+  // I'd argue that the glibc behavior is more reasonable,
+  // but traditionally we've had the BSD behavior.
+  errno = 0;
+#if defined(__GLIBC__)
+  ASSERT_EQ(nullptr, asctime_r(smuggled_null, buf));
+#else
+  ASSERT_EQ(buf, asctime_r(smuggled_null, buf));
+  ASSERT_STREQ("??? ??? ?? ??:??:?? ????\n", buf);
+#endif
+  ASSERT_ERRNO(EINVAL);
+}
+
+TEST(time, asctime_bad_wday) {
+  // This is undefined behavior, but our traditional behavior is to substitute "???".
+  tm tm = { .tm_wday = -1 };
+  char buf[256];
+  ASSERT_EQ(buf, asctime_r(&tm, buf));
+  ASSERT_STREQ("??? Jan  0 00:00:00 1900\n", buf);
+  tm.tm_wday = 7;
+  ASSERT_EQ(buf, asctime_r(&tm, buf));
+  ASSERT_STREQ("??? Jan  0 00:00:00 1900\n", buf);
+}
+
+TEST(time, asctime_bad_mon) {
+  // This is undefined behavior, but our traditional behavior is to substitute "???".
+  tm tm = { .tm_mon = -1 };
+  char buf[256];
+  ASSERT_EQ(buf, asctime_r(&tm, buf));
+  ASSERT_STREQ("Sun ???  0 00:00:00 1900\n", buf);
+  tm.tm_mon = 12;
+  ASSERT_EQ(buf, asctime_r(&tm, buf));
+  ASSERT_STREQ("Sun ???  0 00:00:00 1900\n", buf);
+}
+
+TEST(time, asctime_bad_year) {
+  // This is undefined behavior, but our traditional behavior is to return NULL/EOVERFLOW.
+  tm tm = { .tm_year = 99999 };
+  char buf[256];
+  errno = 0;
+  ASSERT_EQ(nullptr, asctime_r(&tm, buf));
+  ASSERT_ERRNO(EOVERFLOW);
+}
+
 TEST(time, ctime) {
   setenv("TZ", "UTC", 1);
   const time_t t = 0;