Update upstream OpenBSD gdtoa.

Also add a test for the bug that this fixes.

Bug: http://b/152588929
Test: treehugger
Change-Id: I58055b3ebaef457721bb4f5d8a8710025122b2e7
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 878f71c..8206269 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -38,6 +38,8 @@
 /* Ignore all __warn_references in OpenBSD. */
 #define __warn_references(sym,msg)
 
+#define PROTO_NORMAL(x)
+
 /* OpenBSD's <ctype.h> uses these names, which conflicted with stlport.
  * Additionally, we changed the numeric/digit type from N to D for libcxx.
  */
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h
index 9e1cea0..8d621b0 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoa.h
@@ -112,7 +112,18 @@
 extern float  strtof ANSI((CONST char *, char **));
 extern double strtod ANSI((CONST char *, char **));
 extern int __strtodg ANSI((CONST char*, char**, FPI*, Long*, ULong*));
+char	*__hdtoa(double, const char *, int, int *, int *, char **);
+char	*__hldtoa(long double, const char *, int, int *, int *, char **);
+char	*__ldtoa(long double *, int, int, int *, int *, char **);
 
+PROTO_NORMAL(__dtoa);
+PROTO_NORMAL(__gdtoa);
+PROTO_NORMAL(__freedtoa);
+PROTO_NORMAL(__hdtoa);
+PROTO_NORMAL(__hldtoa);
+PROTO_NORMAL(__ldtoa);
+
+__BEGIN_HIDDEN_DECLS
 extern char*	__g_ddfmt  ANSI((char*, double*, int, size_t));
 extern char*	__g_dfmt   ANSI((char*, double*, int, size_t));
 extern char*	__g_ffmt   ANSI((char*, float*,  int, size_t));
@@ -148,6 +159,7 @@
 #define __strtopx(s,se,x) strtorx(s,se,1,x)
 #define __strtopxL(s,se,x) strtorxL(s,se,1,x)
 #endif
+__END_HIDDEN_DECLS
 
 #ifdef __cplusplus
 }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
index 0f3de12..823f2a9 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gdtoaimp.h
@@ -463,7 +463,6 @@
 #define FREE_DTOA_LOCK(n)	/*nothing*/
 #else
 #include "thread_private.h"
-extern void *__dtoa_locks[];
 #define ACQUIRE_DTOA_LOCK(n)	_MUTEX_LOCK(&__dtoa_locks[n])
 #define FREE_DTOA_LOCK(n)	_MUTEX_UNLOCK(&__dtoa_locks[n])
 #endif
@@ -567,6 +566,7 @@
 #define trailz __trailz_D2A
 #define ulp __ulp_D2A
 
+__BEGIN_HIDDEN_DECLS
  extern char *dtoa_result;
  extern CONST double bigtens[], tens[], tinytens[];
  extern unsigned char hexdig[];
@@ -586,8 +586,6 @@
  extern Bigint *d2b ANSI((double, int*, int*));
  extern void decrement ANSI((Bigint*));
  extern Bigint *diff ANSI((Bigint*, Bigint*));
- extern char *dtoa ANSI((double d, int mode, int ndigits,
-			int *decpt, int *sign, char **rve));
  extern char *g__fmt ANSI((char*, char*, char*, int, ULong, size_t));
  extern int gethex ANSI((CONST char**, FPI*, Long*, Bigint**, int));
  extern void __hexdig_init_D2A(Void);
@@ -610,10 +608,10 @@
  extern Bigint *set_ones ANSI((Bigint*, int));
  extern char *strcp ANSI((char*, const char*));
  extern int strtoIg ANSI((CONST char*, char**, FPI*, Long*, Bigint**, int*));
- extern double strtod ANSI((const char *s00, char **se));
  extern Bigint *sum ANSI((Bigint*, Bigint*));
  extern int trailz ANSI((Bigint*));
  extern double ulp ANSI((U*));
+__END_HIDDEN_DECLS
 
 #ifdef __cplusplus
 }
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
index f521f15..d48c9ed 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/gethex.c
@@ -57,11 +57,8 @@
 	static unsigned char *decimalpoint_cache;
 	if (!(s0 = decimalpoint_cache)) {
 		s0 = (unsigned char*)localeconv()->decimal_point;
-		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
-			strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
-			s0 = decimalpoint_cache;
-			}
-		}
+		decimalpoint_cache = strdup(s0);
+	}
 	decimalpoint = s0;
 #endif
 #endif
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
index 45caef4..4a7f798 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/hdtoa.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: hdtoa.c,v 1.3 2015/09/14 12:49:33 guenther Exp $	*/
+/*	$OpenBSD: hdtoa.c,v 1.5 2020/05/31 12:27:19 mortimer Exp $	*/
 /*-
  * Copyright (c) 2004, 2005 David Schultz <das@FreeBSD.ORG>
  * All rights reserved.
@@ -112,7 +112,7 @@
  *
  * Note that the C99 standard does not specify what the leading digit
  * should be for non-zero numbers.  For instance, 0x1.3p3 is the same
- * as 0x2.6p2 is the same as 0x4.cp3.  This implementation chooses the
+ * as 0x2.6p2 is the same as 0x4.cp1.  This implementation chooses the
  * first digit so that subsequent digits are aligned on nibble
  * boundaries (before rounding).
  *
@@ -225,6 +225,7 @@
 	struct ieee_ext *p = (struct ieee_ext *)&e;
 	char *s, *s0;
 	int bufsize;
+	int fbits = 0;
 
 	*sign = p->ext_sign;
 
@@ -273,23 +274,24 @@
 	 */
 	for (s = s0 + bufsize - 1; s > s0 + sigfigs - 1; s--)
 		*s = 0;
-	for (; s > s0 + sigfigs - (EXT_FRACLBITS / 4) - 1 && s > s0; s--) {
+
+	for (fbits = EXT_FRACLBITS / 4; fbits > 0 && s > s0; s--, fbits--) {
 		*s = p->ext_fracl & 0xf;
 		p->ext_fracl >>= 4;
 	}
-#ifdef EXT_FRACHMBITS
-	for (; s > s0; s--) {
-		*s = p->ext_frachm & 0xf;
-		p->ext_frachm >>= 4;
-	}
-#endif
 #ifdef EXT_FRACLMBITS
-	for (; s > s0; s--) {
+	for (fbits = EXT_FRACLMBITS / 4; fbits > 0 && s > s0; s--, fbits--) {
 		*s = p->ext_fraclm & 0xf;
 		p->ext_fraclm >>= 4;
 	}
 #endif
-	for (; s > s0; s--) {
+#ifdef EXT_FRACHMBITS
+	for (fbits = EXT_FRACHMBITS / 4; fbits > 0 && s > s0; s--, fbits--) {
+		*s = p->ext_frachm & 0xf;
+		p->ext_frachm >>= 4;
+	}
+#endif
+	for (fbits = EXT_FRACHBITS / 4; fbits > 0 && s > s0; s--, fbits--) {
 		*s = p->ext_frach & 0xf;
 		p->ext_frach >>= 4;
 	}
@@ -300,7 +302,7 @@
 	 * (partial) nibble, which is dealt with by the next
 	 * statement.  We also tack on the implicit normalization bit.
 	 */
-	*s = p->ext_frach | (1U << ((LDBL_MANT_DIG - 1) % 4));
+	*s = (p->ext_frach | (1U << ((LDBL_MANT_DIG - 1) % 4))) & 0xf;
 
 	/* If ndigits < 0, we are expected to auto-size the precision. */
 	if (ndigits < 0) {
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
index b149f07..79a3104 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/misc.c
@@ -40,6 +40,10 @@
 static double private_mem[PRIVATE_mem], *pmem_next = private_mem;
 #endif
 
+#ifdef MULTIPLE_THREADS
+extern void *__dtoa_locks[];
+#endif
+
  Bigint *
 Balloc
 #ifdef KR_headers
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
index ac2283c..0fb37fd 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtod.c
@@ -114,10 +114,7 @@
 	static int dplen;
 	if (!(s0 = decimalpoint_cache)) {
 		s0 = localeconv()->decimal_point;
-		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
-			strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
-			s0 = decimalpoint_cache;
-			}
+		decimalpoint_cache = strdup(s0);
 		dplen = strlen(s0);
 		}
 	decimalpoint = (char*)s0;
diff --git a/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c b/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c
index 753f6bf..defb474 100644
--- a/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c
+++ b/libc/upstream-openbsd/lib/libc/gdtoa/strtodg.c
@@ -363,10 +363,7 @@
 	static int dplen;
 	if (!(s0 = decimalpoint_cache)) {
 		s0 = localeconv()->decimal_point;
-		if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) {
-			strlcpy(decimalpoint_cache, s0, strlen(s0) + 1);
-			s0 = decimalpoint_cache;
-			}
+		decimalpoint_cache = strdup(s0);
 		dplen = strlen(s0);
 		}
 	decimalpoint = (char*)s0;