Merge "Replace NULL with nullptr"
diff --git a/libc/Android.mk b/libc/Android.mk
index 2c8f554..de0bb41 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -580,6 +580,13 @@
 endif
 
 use_clang := $(USE_CLANG_PLATFORM_BUILD)
+
+# Clang/llvm has incompatible long double (fp128) for x86_64.
+# https://llvm.org/bugs/show_bug.cgi?id=23897
+ifeq ($(TARGET_ARCH),x86_64)
+  use_clang := false
+endif
+
 ifeq ($(use_clang),)
   use_clang := false
 endif
diff --git a/libc/include/sys/procfs.h b/libc/include/sys/procfs.h
index b5b1a46..7ef5023 100644
--- a/libc/include/sys/procfs.h
+++ b/libc/include/sys/procfs.h
@@ -39,6 +39,10 @@
 
 typedef fpregset_t elf_fpregset_t;
 
+#if defined(__i386__)
+typedef struct user_fpxregs_struct elf_fpxregset_t;
+#endif
+
 typedef elf_gregset_t prgregset_t;
 typedef elf_fpregset_t prfpregset_t;
 
diff --git a/libc/include/sys/user.h b/libc/include/sys/user.h
index b370add..d63fe6a 100644
--- a/libc/include/sys/user.h
+++ b/libc/include/sys/user.h
@@ -47,7 +47,7 @@
   long fos;
   long st_space[20];
 };
-struct user_fxsr_struct {
+struct user_fpxregs_struct {
   unsigned short cwd;
   unsigned short swd;
   unsigned short twd;
diff --git a/libc/include/sysexits.h b/libc/include/sysexits.h
new file mode 100644
index 0000000..e244836
--- /dev/null
+++ b/libc/include/sysexits.h
@@ -0,0 +1,119 @@
+/*	$OpenBSD: sysexits.h,v 1.5 2003/06/02 19:34:12 millert Exp $	*/
+/*	$NetBSD: sysexits.h,v 1.4 1994/10/26 00:56:33 cgd Exp $	*/
+
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)sysexits.h	4.8 (Berkeley) 4/3/91
+ */
+
+#ifndef	_SYSEXITS_H_
+#define	_SYSEXITS_H_
+
+/*
+ *  SYSEXITS.H -- Exit status codes for system programs.
+ *
+ *	This include file attempts to categorize possible error
+ *	exit statuses for system programs, notably delivermail
+ *	and the Berkeley network.
+ *
+ *	Error numbers begin at EX__BASE to reduce the possibility of
+ *	clashing with other exit statuses that random programs may
+ *	already return.  The meaning of the codes is approximately
+ *	as follows:
+ *
+ *	EX_USAGE -- The command was used incorrectly, e.g., with
+ *		the wrong number of arguments, a bad flag, a bad
+ *		syntax in a parameter, or whatever.
+ *	EX_DATAERR -- The input data was incorrect in some way.
+ *		This should only be used for user's data & not
+ *		system files.
+ *	EX_NOINPUT -- An input file (not a system file) did not
+ *		exist or was not readable.  This could also include
+ *		errors like "No message" to a mailer (if it cared
+ *		to catch it).
+ *	EX_NOUSER -- The user specified did not exist.  This might
+ *		be used for mail addresses or remote logins.
+ *	EX_NOHOST -- The host specified did not exist.  This is used
+ *		in mail addresses or network requests.
+ *	EX_UNAVAILABLE -- A service is unavailable.  This can occur
+ *		if a support program or file does not exist.  This
+ *		can also be used as a catchall message when something
+ *		you wanted to do doesn't work, but you don't know
+ *		why.
+ *	EX_SOFTWARE -- An internal software error has been detected.
+ *		This should be limited to non-operating system related
+ *		errors as possible.
+ *	EX_OSERR -- An operating system error has been detected.
+ *		This is intended to be used for such things as "cannot
+ *		fork", "cannot create pipe", or the like.  It includes
+ *		things like getuid returning a user that does not
+ *		exist in the passwd file.
+ *	EX_OSFILE -- Some system file (e.g., /etc/passwd, /var/run/utmp,
+ *		etc.) does not exist, cannot be opened, or has some
+ *		sort of error (e.g., syntax error).
+ *	EX_CANTCREAT -- A (user specified) output file cannot be
+ *		created.
+ *	EX_IOERR -- An error occurred while doing I/O on some file.
+ *	EX_TEMPFAIL -- temporary failure, indicating something that
+ *		is not really an error.  In sendmail, this means
+ *		that a mailer (e.g.) could not create a connection,
+ *		and the request should be reattempted later.
+ *	EX_PROTOCOL -- the remote system returned something that
+ *		was "not possible" during a protocol exchange.
+ *	EX_NOPERM -- You did not have sufficient permission to
+ *		perform the operation.  This is not intended for
+ *		file system problems, which should use EX_NOINPUT or
+ *		EX_CANTCREAT, but rather for higher level permissions.
+ *	EX_CONFIG -- Something was found in an unconfigured or
+ *		misconfigured state.
+ */
+
+#define EX_OK		0	/* successful termination */
+
+#define EX__BASE	64	/* base value for error messages */
+
+#define EX_USAGE	64	/* command line usage error */
+#define EX_DATAERR	65	/* data format error */
+#define EX_NOINPUT	66	/* cannot open input */
+#define EX_NOUSER	67	/* addressee unknown */
+#define EX_NOHOST	68	/* host name unknown */
+#define EX_UNAVAILABLE	69	/* service unavailable */
+#define EX_SOFTWARE	70	/* internal software error */
+#define EX_OSERR	71	/* system error (e.g., can't fork) */
+#define EX_OSFILE	72	/* critical OS file missing */
+#define EX_CANTCREAT	73	/* can't create (user) output file */
+#define EX_IOERR	74	/* input/output error */
+#define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
+#define EX_PROTOCOL	76	/* remote error in protocol */
+#define EX_NOPERM	77	/* permission denied */
+#define EX_CONFIG	78	/* configuration error */
+
+#define EX__MAX		78	/* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
diff --git a/libm/Android.mk b/libm/Android.mk
index bc4c86d..7a7e3b0 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -3,6 +3,12 @@
 
 bionic_coverage := false
 
+# Clang/llvm has incompatible long double (fp128) for x86_64.
+# https://llvm.org/bugs/show_bug.cgi?id=23897
+ifeq ($(TARGET_ARCH),x86_64)
+libm_clang := false
+endif
+
 # -----------------------------------------------------------------------------
 # libm.a
 # -----------------------------------------------------------------------------
@@ -473,7 +479,7 @@
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/upstream-freebsd/lib/msun/src/
 LOCAL_C_INCLUDES_64 += $(LOCAL_PATH)/upstream-freebsd/lib/msun/ld128/
 
-LOCAL_CLANG := true
+LOCAL_CLANG := $(libm_clang)
 LOCAL_ARM_MODE := arm
 LOCAL_CFLAGS := \
     -DFLT_EVAL_METHOD=0 \
@@ -514,7 +520,7 @@
 LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libm.map
 
 LOCAL_MODULE := libm
-LOCAL_CLANG := true
+LOCAL_CLANG := $(libm_clang)
 LOCAL_SYSTEM_SHARED_LIBRARIES := libc
 LOCAL_WHOLE_STATIC_LIBRARIES := libm
 
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 1f00771..5d54089 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1159,7 +1159,7 @@
 
   ZipEntry entry;
 
-  if (FindEntry(handle, ZipEntryName(file_path), &entry) != 0) {
+  if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
     // Entry was not found.
     close(fd);
     return -1;
@@ -1337,7 +1337,7 @@
   }
 
   // Read the ELF header and load the segments.
-  ElfReader elf_reader(realpath.c_str(), fd, file_offset);
+  ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size);
   if (!elf_reader.Load(extinfo)) {
     return nullptr;
   }
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index f586b08..30118e3 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -133,8 +133,8 @@
                                       MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \
                                       MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE))
 
-ElfReader::ElfReader(const char* name, int fd, off64_t file_offset)
-    : name_(name), fd_(fd), file_offset_(file_offset),
+ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size)
+    : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size),
       phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0),
       load_start_(nullptr), load_size_(0), load_bias_(0),
       loaded_phdr_(nullptr) {
@@ -377,6 +377,20 @@
     ElfW(Addr) file_page_start = PAGE_START(file_start);
     ElfW(Addr) file_length = file_end - file_page_start;
 
+    if (file_size_ <= 0) {
+      DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_);
+      return false;
+    }
+
+    if (file_end >= static_cast<size_t>(file_size_)) {
+      DL_ERR("invalid ELF file \"%s\" load segment[%zd]:"
+          " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")",
+          name_, i, reinterpret_cast<void*>(phdr->p_offset),
+          reinterpret_cast<void*>(phdr->p_filesz),
+          reinterpret_cast<void*>(file_end), file_size_);
+      return false;
+    }
+
     if (file_length != 0) {
       void* seg_addr = mmap64(reinterpret_cast<void*>(seg_page_start),
                             file_length,
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 50f2117..3affa66 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -39,7 +39,7 @@
 
 class ElfReader {
  public:
-  ElfReader(const char* name, int fd, off64_t file_offset);
+  ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size);
   ~ElfReader();
 
   bool Load(const android_dlextinfo* extinfo);
@@ -62,6 +62,7 @@
   const char* name_;
   int fd_;
   off64_t file_offset_;
+  off64_t file_size_;
 
   ElfW(Ehdr) header_;
   size_t phdr_num_;
diff --git a/tests/Android.mk b/tests/Android.mk
index 84d3426..8aba70b 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -137,6 +137,11 @@
 libBionicStandardTests_ldlibs_host := \
     -lrt \
 
+# Clang/llvm has incompatible long double (fp128) for x86_64.
+# https://llvm.org/bugs/show_bug.cgi?id=23897
+# This affects most of math_test.cpp.
+libBionicStandardTests_clang_target := false
+
 module := libBionicStandardTests
 module_tag := optional
 build_type := target
diff --git a/tests/libs/dlopen_b.cpp b/tests/libs/dlopen_b.cpp
index 34f2881..5291d81 100644
--- a/tests/libs/dlopen_b.cpp
+++ b/tests/libs/dlopen_b.cpp
@@ -1,7 +1,15 @@
 #include <dlfcn.h>
 extern "C" void *dlopen_b() {
+  // TODO (dimitry): this is to work around http://b/20049306
+  // remove once it is fixed
+  static int dummy = 0;
+
   // This is not supposed to succeed. Even though this library has DT_RUNPATH
   // for libtest_dt_runpath_x.so, it is not taked into account for dlopen.
   void *handle = dlopen("libtest_dt_runpath_x.so", RTLD_NOW);
-  return handle;
+  if (handle != nullptr) {
+    dummy++;
+    return handle;
+  }
+  return nullptr;
 }