Merge "Update to v4.17.3 kernel headers."
diff --git a/libc/bionic/mbrtoc32.cpp b/libc/bionic/mbrtoc32.cpp
index f004b78..88a077c 100644
--- a/libc/bionic/mbrtoc32.cpp
+++ b/libc/bionic/mbrtoc32.cpp
@@ -127,7 +127,7 @@
     // Malformed input; redundant encoding.
     return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
-  if ((c32 >= 0xd800 && c32 <= 0xdfff) || c32 == 0xfffe || c32 == 0xffff) {
+  if ((c32 >= 0xd800 && c32 <= 0xdfff) || (c32 > 0x10ffff)) {
     // Malformed input; invalid code points.
     return mbstate_reset_and_return_illegal(EILSEQ, state);
   }
diff --git a/libc/dns/resolv/res_send.c b/libc/dns/resolv/res_send.c
index 18bb752..cc09238 100644
--- a/libc/dns/resolv/res_send.c
+++ b/libc/dns/resolv/res_send.c
@@ -97,6 +97,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <netdb.h>
+#include <poll.h>
 #ifdef ANDROID_CHANGES
 #include "resolv_netid.h"
 #include "resolv_private.h"
@@ -133,8 +134,6 @@
 #define EXT(res) ((res)->_u._ext)
 #define DBG 0
 
-static const int highestFD = FD_SETSIZE - 1;
-
 /* Forward. */
 
 static int		get_salen __P((const struct sockaddr *));
@@ -150,16 +149,10 @@
 			       const struct sockaddr *, int);
 static void		Perror(const res_state, FILE *, const char *, int);
 static int		sock_eq(struct sockaddr *, struct sockaddr *);
-#ifdef NEED_PSELECT
-static int		pselect(int, void *, void *, void *,
-				struct timespec *,
-				const sigset_t *);
-#endif
 void res_pquery(const res_state, const u_char *, int, FILE *);
 static int connect_with_timeout(int sock, const struct sockaddr *nsap,
 			socklen_t salen, int sec);
-static int retrying_select(const int sock, fd_set *readset, fd_set *writeset,
-			const struct timespec *finish);
+static int retrying_poll(const int sock, short events, const struct timespec* finish);
 
 /* BIONIC-BEGIN: implement source port randomization */
 typedef union {
@@ -802,10 +795,6 @@
 			res_nclose(statp);
 
 		statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
-		if (statp->_vcsock > highestFD) {
-			res_nclose(statp);
-			errno = ENOTSOCK;
-		}
 		if (statp->_vcsock < 0) {
 			switch (errno) {
 			case EPROTONOSUPPORT:
@@ -849,7 +838,7 @@
 			 * determining whether this was really a timeout or e.g. ECONNREFUSED. Since
 			 * currently both cases are handled in the same way, there is no need to
 			 * change this (yet). If we ever need to reliably distinguish between these
-			 * cases, both connect_with_timeout() and retrying_select() need to be
+			 * cases, both connect_with_timeout() and retrying_poll() need to be
 			 * modified, though.
 			 */
 			*rcode = RCODE_TIMEOUT;
@@ -983,8 +972,6 @@
 connect_with_timeout(int sock, const struct sockaddr *nsap, socklen_t salen, int sec)
 {
 	int res, origflags;
-	fd_set rset, wset;
-	struct timespec now, timeout, finish;
 
 	origflags = fcntl(sock, F_GETFL, 0);
 	fcntl(sock, F_SETFL, origflags | O_NONBLOCK);
@@ -995,14 +982,14 @@
 		goto done;
 	}
 	if (res != 0) {
-		now = evNowTime();
-		timeout = evConsTime((long)sec, 0L);
-		finish = evAddTime(now, timeout);
+		struct timespec now = evNowTime();
+		struct timespec timeout = evConsTime((long)sec, 0L);
+		struct timespec finish = evAddTime(now, timeout);
 		if (DBG) {
 			async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "  %d send_vc\n", sock);
 		}
 
-		res = retrying_select(sock, &rset, &wset, &finish);
+		res = retrying_poll(sock, POLLIN | POLLOUT, &finish);
 		if (res <= 0) {
 			res = -1;
 		}
@@ -1017,37 +1004,25 @@
 }
 
 static int
-retrying_select(const int sock, fd_set *readset, fd_set *writeset, const struct timespec *finish)
-{
+retrying_poll(const int sock, const short events, const struct timespec* finish) {
 	struct timespec now, timeout;
-	int n, error;
-	socklen_t len;
-
 
 retry:
 	if (DBG) {
-		async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_select\n", sock);
+		async_safe_format_log(ANDROID_LOG_DEBUG, "libc", "  %d retrying_poll\n", sock);
 	}
 
 	now = evNowTime();
-	if (readset) {
-		FD_ZERO(readset);
-		FD_SET(sock, readset);
-	}
-	if (writeset) {
-		FD_ZERO(writeset);
-		FD_SET(sock, writeset);
-	}
 	if (evCmpTime(*finish, now) > 0)
 		timeout = evSubTime(*finish, now);
 	else
 		timeout = evConsTime(0L, 0L);
-
-	n = pselect(sock + 1, readset, writeset, NULL, &timeout, NULL);
+	struct pollfd fds = { .fd = sock, .events = events };
+	int n = ppoll(&fds, 1, &timeout, /*sigmask=*/NULL);
 	if (n == 0) {
 		if (DBG) {
 			async_safe_format_log(ANDROID_LOG_DEBUG, " libc",
-				"  %d retrying_select timeout\n", sock);
+				"  %d retrying_poll timeout\n", sock);
 		}
 		errno = ETIMEDOUT;
 		return 0;
@@ -1057,17 +1032,18 @@
 			goto retry;
 		if (DBG) {
 			async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
-				"  %d retrying_select got error %d\n",sock, n);
+				"  %d retrying_poll got error %d\n",sock, n);
 		}
 		return n;
 	}
-	if ((readset && FD_ISSET(sock, readset)) || (writeset && FD_ISSET(sock, writeset))) {
-		len = sizeof(error);
+	if (fds.revents & (POLLIN | POLLOUT | POLLERR)) {
+		int error;
+		socklen_t len = sizeof(error);
 		if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0 || error) {
 			errno = error;
 			if (DBG) {
 				async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
-					"  %d retrying_select dot error2 %d\n", sock, errno);
+					"  %d retrying_poll dot error2 %d\n", sock, errno);
 			}
 
 			return -1;
@@ -1075,7 +1051,7 @@
 	}
 	if (DBG) {
 		async_safe_format_log(ANDROID_LOG_DEBUG, "libc",
-			"  %d retrying_select returning %d\n",sock, n);
+			"  %d retrying_poll returning %d\n",sock, n);
 	}
 
 	return n;
@@ -1095,7 +1071,6 @@
 	const struct sockaddr *nsap;
 	int nsaplen;
 	struct timespec now, timeout, finish, done;
-	fd_set dsmask;
 	struct sockaddr_storage from;
 	socklen_t fromlen;
 	int resplen, seconds, n, s;
@@ -1104,10 +1079,6 @@
 	nsaplen = get_salen(nsap);
 	if (EXT(statp).nssocks[ns] == -1) {
 		EXT(statp).nssocks[ns] = socket(nsap->sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-		if (EXT(statp).nssocks[ns] > highestFD) {
-			res_nclose(statp);
-			errno = ENOTSOCK;
-		}
 		if (EXT(statp).nssocks[ns] < 0) {
 			switch (errno) {
 			case EPROTONOSUPPORT:
@@ -1185,7 +1156,7 @@
 	timeout = evConsTime((long)seconds, 0L);
 	finish = evAddTime(now, timeout);
 retry:
-	n = retrying_select(s, &dsmask, NULL, &finish);
+	n = retrying_poll(s, POLLIN, &finish);
 
 	if (n == 0) {
 		*rcode = RCODE_TIMEOUT;
@@ -1194,7 +1165,7 @@
 		return (0);
 	}
 	if (n < 0) {
-		Perror(statp, stderr, "select", errno);
+		Perror(statp, stderr, "poll", errno);
 		res_nclose(statp);
 		return (0);
 	}
@@ -1367,29 +1338,3 @@
 		return 0;
 	}
 }
-
-#ifdef NEED_PSELECT
-/* XXX needs to move to the porting library. */
-static int
-pselect(int nfds, void *rfds, void *wfds, void *efds,
-	struct timespec *tsp, const sigset_t *sigmask)
-{
-	struct timeval tv, *tvp;
-	sigset_t sigs;
-	int n;
-
-	if (tsp) {
-		tvp = &tv;
-		tv = evTimeVal(*tsp);
-	} else
-		tvp = NULL;
-	if (sigmask)
-		sigprocmask(SIG_SETMASK, sigmask, &sigs);
-	n = select(nfds, rfds, wfds, efds, tvp);
-	if (sigmask)
-		sigprocmask(SIG_SETMASK, &sigs, NULL);
-	if (tsp)
-		*tsp = evTimeSpec(tv);
-	return (n);
-}
-#endif
diff --git a/libc/include/netinet/ip_icmp.h b/libc/include/netinet/ip_icmp.h
index 7510592..d6f89bc 100644
--- a/libc/include/netinet/ip_icmp.h
+++ b/libc/include/netinet/ip_icmp.h
@@ -35,9 +35,11 @@
 #ifndef _NETINET_IP_ICMP_H_
 #define _NETINET_IP_ICMP_H_
 
-#include <netinet/ip.h>
 #include <sys/cdefs.h>
 
+#include <linux/icmp.h>
+#include <netinet/ip.h>
+
 __BEGIN_DECLS
 
 /*
diff --git a/libc/include/sys/un.h b/libc/include/sys/un.h
index 3e1c429..03ef5e4 100644
--- a/libc/include/sys/un.h
+++ b/libc/include/sys/un.h
@@ -33,4 +33,9 @@
 #include <linux/un.h>
 #include <sys/cdefs.h>
 
+#if defined(__USE_BSD) || defined(__USE_GNU)
+#include <string.h>
+#define SUN_LEN(__ptr) (offsetof(struct sockaddr_un, sun_path) + strlen((__ptr)->sun_path))
+#endif
+
 #endif
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index b24be92..54354a8 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -213,7 +213,8 @@
 
 bool ElfReader::VerifyElfHeader() {
   if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) {
-    DL_ERR("\"%s\" has bad ELF magic", name_.c_str());
+    DL_ERR("\"%s\" has bad ELF magic: %02x%02x%02x%02x", name_.c_str(),
+           header_.e_ident[0], header_.e_ident[1], header_.e_ident[2], header_.e_ident[3]);
     return false;
   }
 
diff --git a/tests/Android.bp b/tests/Android.bp
index 707d0fe..b5efb8c 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -108,6 +108,7 @@
         "net_if_test.cpp",
         "netinet_ether_test.cpp",
         "netinet_in_test.cpp",
+        "netinet_ip_icmp_test.cpp",
         "netinet_udp_test.cpp",
         "nl_types_test.cpp",
         "pthread_test.cpp",
@@ -166,6 +167,7 @@
         "sys_ttydefaults_test.cpp",
         "sys_types_test.cpp",
         "sys_uio_test.cpp",
+        "sys_un_test.cpp",
         "sys_vfs_test.cpp",
         "sys_xattr_test.cpp",
         "system_properties_test.cpp",
@@ -396,10 +398,8 @@
 
 // -----------------------------------------------------------------------------
 // Tests for the device using bionic's .so. Run with:
-//   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
-//   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
-//   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc32
-//   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc64
+//   adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests
+//   adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests
 // -----------------------------------------------------------------------------
 cc_defaults {
     name: "bionic_unit_tests_defaults",
@@ -610,8 +610,8 @@
 
 // -----------------------------------------------------------------------------
 // Tests for the device linked against bionic's static library. Run with:
-//   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
-//   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
+//   adb shell /data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static
+//   adb shell /data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static
 // -----------------------------------------------------------------------------
 cc_test {
     name: "bionic-unit-tests-static",
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index ec27932..1e3d9c8 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -173,7 +173,7 @@
   extinfo.library_fd_offset = 0;
   handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
   ASSERT_TRUE(handle_ == nullptr);
-  ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic", dlerror());
+  ASSERT_EQ("dlopen failed: \"" + lib_path + "\" has bad ELF magic: 504b0304", dlerror());
 
   // Check if dlsym works after unsuccessful dlopen().
   // Supply non-exiting one to make linker visit every soinfo.
diff --git a/tests/grp_pwd_test.cpp b/tests/grp_pwd_test.cpp
index 615f374..2df1ef0 100644
--- a/tests/grp_pwd_test.cpp
+++ b/tests/grp_pwd_test.cpp
@@ -279,7 +279,14 @@
       EXPECT_STREQ("/data", pwd->pw_dir) << "pwd->pw_uid: " << pwd->pw_uid;
     }
 
-    EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
+    // TODO(b/27999086): fix this check with the OEM range
+    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+    // yet, so therefore we do not check for uid's in the OEM range.
+    if (!(pwd->pw_uid >= 2900 && pwd->pw_uid <= 2999) &&
+        !(pwd->pw_uid >= 5000 && pwd->pw_uid <= 5999)) {
+      EXPECT_EQ(0U, uids.count(pwd->pw_uid)) << "pwd->pw_uid: " << pwd->pw_uid;
+    }
     uids.emplace(pwd->pw_uid);
   }
   endpwent();
@@ -522,7 +529,14 @@
     EXPECT_STREQ(grp->gr_name, grp->gr_mem[0]) << "grp->gr_gid: " << grp->gr_gid;
     EXPECT_TRUE(grp->gr_mem[1] == NULL) << "grp->gr_gid: " << grp->gr_gid;
 
-    EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
+    // TODO(b/27999086): fix this check with the OEM range
+    // If OEMs add their own AIDs to private/android_filesystem_config.h, this check will fail.
+    // Long term we want to create a better solution for OEMs adding AIDs, but we're not there
+    // yet, so therefore we do not check for gid's in the OEM range.
+    if (!(grp->gr_gid >= 2900 && grp->gr_gid <= 2999) &&
+        !(grp->gr_gid >= 5000 && grp->gr_gid <= 5999)) {
+      EXPECT_EQ(0U, gids.count(grp->gr_gid)) << "grp->gr_gid: " << grp->gr_gid;
+    }
     gids.emplace(grp->gr_gid);
   }
   endgrent();
diff --git a/tests/netinet_ip_icmp_test.cpp b/tests/netinet_ip_icmp_test.cpp
new file mode 100644
index 0000000..b3b4f65
--- /dev/null
+++ b/tests/netinet_ip_icmp_test.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <netinet/ip_icmp.h>
+
+#include <gtest/gtest.h>
+
+TEST(netinet_ip_icmp, struct_icmphdr) {
+  icmphdr hdr = { .type = ICMP_ECHO };
+  ASSERT_EQ(ICMP_ECHO, hdr.type);
+  ASSERT_EQ(0, hdr.code);
+  ASSERT_EQ(0, hdr.checksum);
+  ASSERT_EQ(0, hdr.un.echo.id);
+  ASSERT_EQ(0, hdr.un.echo.sequence);
+  ASSERT_EQ(0U, hdr.un.gateway);
+  ASSERT_EQ(0, hdr.un.frag.mtu);
+}
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index af682a9..f2f6e01 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -2499,6 +2499,11 @@
   }
 }
 
+TEST(pthread, pthread_barrier_init_zero_count) {
+  pthread_barrier_t barrier;
+  ASSERT_EQ(EINVAL, pthread_barrier_init(&barrier, nullptr, 0));
+}
+
 TEST(pthread, pthread_spinlock_smoke) {
   pthread_spinlock_t lock;
   ASSERT_EQ(0, pthread_spin_init(&lock, 0));
diff --git a/tests/sys_un_test.cpp b/tests/sys_un_test.cpp
new file mode 100644
index 0000000..08a4d0f
--- /dev/null
+++ b/tests/sys_un_test.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/un.h>
+
+#include <string.h>
+#include <gtest/gtest.h>
+
+TEST(sys_un, SUN_LEN_macro) {
+  sockaddr_un sun = {};
+  sun.sun_family = 1;
+  strcpy(sun.sun_path, "hello");
+  ASSERT_EQ(2U + strlen("hello"), SUN_LEN(&sun));
+}
diff --git a/tests/uchar_test.cpp b/tests/uchar_test.cpp
index 8b29667..2b4c4d3 100644
--- a/tests/uchar_test.cpp
+++ b/tests/uchar_test.cpp
@@ -322,6 +322,35 @@
 #endif
 }
 
+TEST(uchar, mbrtoc32_valid_non_characters) {
+#if HAVE_UCHAR
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  char32_t out[8] = {};
+  ASSERT_EQ(3U, mbrtoc32(out, "\xef\xbf\xbe", 3, nullptr));
+  ASSERT_EQ(0xfffeU, out[0]);
+  ASSERT_EQ(3U, mbrtoc32(out, "\xef\xbf\xbf", 3, nullptr));
+  ASSERT_EQ(0xffffU, out[0]);
+#else
+  GTEST_LOG_(INFO) << "uchar.h is unavailable.\n";
+#endif
+}
+
+TEST(uchar, mbrtoc32_out_of_range) {
+#if HAVE_UCHAR
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  char32_t out[8] = {};
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(-1), mbrtoc32(out, "\xf5\x80\x80\x80", 4, nullptr));
+  ASSERT_EQ(EILSEQ, errno);
+#else
+  GTEST_LOG_(INFO) << "uchar.h is unavailable.\n";
+#endif
+}
+
 TEST(uchar, mbrtoc32) {
 #if HAVE_UCHAR
   char32_t out[8];
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index b42e13c..e2def07 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -305,6 +305,28 @@
   ASSERT_EQ(EILSEQ, errno);
 }
 
+TEST(wchar, mbrtowc_valid_non_characters) {
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  wchar_t out[8] = {};
+
+  ASSERT_EQ(3U, mbrtowc(out, "\xef\xbf\xbe", 3, nullptr));
+  ASSERT_EQ(static_cast<wchar_t>(0xfffe), out[0]);
+  ASSERT_EQ(3U, mbrtowc(out, "\xef\xbf\xbf", 3, nullptr));
+  ASSERT_EQ(static_cast<wchar_t>(0xffff), out[0]);
+}
+
+TEST(wchar, mbrtowc_out_of_range) {
+  ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
+  uselocale(LC_GLOBAL_LOCALE);
+
+  wchar_t out[8] = {};
+  errno = 0;
+  ASSERT_EQ(static_cast<size_t>(-1), mbrtowc(out, "\xf5\x80\x80\x80", 4, nullptr));
+  ASSERT_EQ(EILSEQ, errno);
+}
+
 static void test_mbrtowc_incomplete(mbstate_t* ps) {
   ASSERT_STREQ("C.UTF-8", setlocale(LC_CTYPE, "C.UTF-8"));
   uselocale(LC_GLOBAL_LOCALE);