Apply recent strto* fix, add new tests.

The behavior with "0xy" was wrong: we'd swallow the 'x'.

Bug: N/A
Test: ran tests
Change-Id: I2464d22a2408e99880303876306f18a25c390ad9
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 9b16da7..baf5057 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -40,6 +40,7 @@
 /* Ignore all DEF_STRONG/DEF_WEAK in OpenBSD. */
 #define DEF_STRONG(sym)
 #define DEF_WEAK(sym)
+#define __weak_alias __strong_alias
 
 /* Ignore all __warn_references in OpenBSD. */
 #define __warn_references(sym,msg)
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
index 2fc04e4..74e3556 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoimax.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtoimax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $	*/
+/*	$OpenBSD: strtoimax.c,v 1.4 2017/07/06 16:23:11 millert Exp $	*/
 /*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
@@ -74,8 +74,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -148,3 +148,4 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtoimax);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
index 86cec35..599d235 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtol.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtol.c,v 1.10 2014/09/13 20:10:12 schwarze Exp $ */
+/*	$OpenBSD: strtol.c,v 1.12 2017/07/06 16:23:11 millert Exp $ */
 /*
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -75,8 +75,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -148,3 +148,4 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtol);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
index cf82c8e..d21a249 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoll.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtoll.c,v 1.8 2014/09/13 20:10:12 schwarze Exp $ */
+/*	$OpenBSD: strtoll.c,v 1.10 2017/07/06 16:23:11 millert Exp $ */
 /*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
@@ -77,8 +77,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -151,5 +151,6 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtoll);
 
-__strong_alias(strtoq, strtoll);
+__weak_alias(strtoq, strtoll);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
index 2aa41b7..6667bea 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoul.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtoul.c,v 1.9 2014/09/13 20:10:12 schwarze Exp $ */
+/*	$OpenBSD: strtoul.c,v 1.11 2017/07/06 16:23:11 millert Exp $ */
 /*
  * Copyright (c) 1990 The Regents of the University of California.
  * All rights reserved.
@@ -69,8 +69,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -107,3 +107,4 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtoul);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
index 8464176..d7733e40 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoull.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtoull.c,v 1.7 2014/09/13 20:10:12 schwarze Exp $ */
+/*	$OpenBSD: strtoull.c,v 1.9 2017/07/06 16:23:11 millert Exp $ */
 /*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
@@ -71,8 +71,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -109,5 +109,6 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtoull);
 
-__strong_alias(strtouq, strtoull);
+__weak_alias(strtouq, strtoull);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
index c73f7e5..348184c 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/strtoumax.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: strtoumax.c,v 1.2 2014/09/13 20:10:12 schwarze Exp $	*/
+/*	$OpenBSD: strtoumax.c,v 1.4 2017/07/06 16:23:11 millert Exp $	*/
 /*
  * Copyright (c) 1992 The Regents of the University of California.
  * All rights reserved.
@@ -68,8 +68,8 @@
 		if (c == '+')
 			c = *s++;
 	}
-	if ((base == 0 || base == 16) &&
-	    c == '0' && (*s == 'x' || *s == 'X')) {
+	if ((base == 0 || base == 16) && c == '0' &&
+	    (*s == 'x' || *s == 'X') && isxdigit((unsigned char)s[1])) {
 		c = s[1];
 		s += 2;
 		base = 16;
@@ -106,3 +106,4 @@
 		*endptr = (char *) (any ? s - 1 : nptr);
 	return (acc);
 }
+DEF_STRONG(strtoumax);
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 4c4c102..c724f74 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -555,54 +555,6 @@
   close(fd);
 }
 
-TEST(stdlib, strtol_EINVAL) {
-  errno = 0;
-  strtol("123", NULL, -1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtol("123", NULL, 1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtol("123", NULL, 37);
-  ASSERT_EQ(EINVAL, errno);
-}
-
-TEST(stdlib, strtoll_EINVAL) {
-  errno = 0;
-  strtoll("123", NULL, -1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoll("123", NULL, 1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoll("123", NULL, 37);
-  ASSERT_EQ(EINVAL, errno);
-}
-
-TEST(stdlib, strtoul_EINVAL) {
-  errno = 0;
-  strtoul("123", NULL, -1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoul("123", NULL, 1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoul("123", NULL, 37);
-  ASSERT_EQ(EINVAL, errno);
-}
-
-TEST(stdlib, strtoull_EINVAL) {
-  errno = 0;
-  strtoull("123", NULL, -1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoull("123", NULL, 1);
-  ASSERT_EQ(EINVAL, errno);
-  errno = 0;
-  strtoull("123", NULL, 37);
-  ASSERT_EQ(EINVAL, errno);
-}
-
 TEST(stdlib, getsubopt) {
   char* const tokens[] = {
     const_cast<char*>("a"),
@@ -648,3 +600,51 @@
   // "mblen() shall ... return 0 (if s points to the null byte)".
   EXPECT_EQ(0, mblen("", 1));
 }
+
+template <typename T>
+static void CheckStrToInt(T fn(const char* s, char** end, int base)) {
+  char* end_p;
+
+  // Negative base => invalid.
+  errno = 0;
+  ASSERT_EQ(T(0), fn("123", &end_p, -1));
+  ASSERT_EQ(EINVAL, errno);
+
+  // Base 1 => invalid (base 0 means "please guess").
+  errno = 0;
+  ASSERT_EQ(T(0), fn("123", &end_p, 1));
+  ASSERT_EQ(EINVAL, errno);
+
+  // Base > 36 => invalid.
+  errno = 0;
+  ASSERT_EQ(T(0), fn("123", &end_p, 37));
+  ASSERT_EQ(EINVAL, errno);
+
+  // If we see "0x" *not* followed by a hex digit, we shouldn't swallow the 'x'.
+  ASSERT_EQ(T(0), fn("0xy", &end_p, 16));
+  ASSERT_EQ('x', *end_p);
+}
+
+TEST(stdlib, strtol_smoke) {
+  CheckStrToInt(strtol);
+}
+
+TEST(stdlib, strtoll_smoke) {
+  CheckStrToInt(strtoll);
+}
+
+TEST(stdlib, strtoul_smoke) {
+  CheckStrToInt(strtoul);
+}
+
+TEST(stdlib, strtoull_smoke) {
+  CheckStrToInt(strtoull);
+}
+
+TEST(stdlib, strtoimax_smoke) {
+  CheckStrToInt(strtoimax);
+}
+
+TEST(stdlib, strtoumax_smoke) {
+  CheckStrToInt(strtoumax);
+}