Merge "Remove debug.ld.greylist_disabled property"
diff --git a/docs/libc_assembler.md b/docs/libc_assembler.md
index 44c0036..43bcfc7 100644
--- a/docs/libc_assembler.md
+++ b/docs/libc_assembler.md
@@ -10,7 +10,8 @@
 * Rerun the benchmarks using the updated image that uses the code for
 the new routine. See the [Performance](#Performance) section for details about
 benchmarking.
-* Verify that unwind information for new routine looks sane. See the [Unwind Info](#unwind-info) section for details about how to verify this.
+* Verify that unwind information for new routine looks correct. See
+the [Unwind Info](#unwind-info) section for details about how to verify this.
 
 When benchmarking, it's best to verify on the latest Pixel device supported.
 Make sure that you benchmark both the big and little cores to verify that
diff --git a/libc/Android.bp b/libc/Android.bp
index 48c9dd0..b278774 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -525,6 +525,7 @@
         "upstream-openbsd/lib/libc/stdlib/llabs.c",
         "upstream-openbsd/lib/libc/stdlib/lldiv.c",
         "upstream-openbsd/lib/libc/stdlib/lsearch.c",
+        "upstream-openbsd/lib/libc/stdlib/recallocarray.c",
         "upstream-openbsd/lib/libc/stdlib/remque.c",
         "upstream-openbsd/lib/libc/stdlib/setenv.c",
         "upstream-openbsd/lib/libc/stdlib/tfind.c",
diff --git a/libc/NOTICE b/libc/NOTICE
index 2fd674b..7f2e8b0 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -3004,7 +3004,7 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
@@ -4244,7 +4244,7 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2005-2014 Rich Felker
+Copyright (c) 2005-2018 Rich Felker
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -4602,7 +4602,23 @@
 
 -------------------------------------------------------------------
 
-Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
+Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff --git a/libc/arch-arm/bionic/__restore.S b/libc/arch-arm/bionic/__restore.S
index 8c1e41d..5291743 100644
--- a/libc/arch-arm/bionic/__restore.S
+++ b/libc/arch-arm/bionic/__restore.S
@@ -28,13 +28,14 @@
 
 #include <private/bionic_asm.h>
 
-// gdb is smart enough to unwind through signal frames with just the regular
+// gdb is able to unwind through signal frames with just the regular
 // CFI information but libgcc and libunwind both need extra help. We do this
 // by using .fnstart/.fnend and inserting a nop before both __restore and
 // __restore_rt (but covered by the .fnstart/.fnend) so that although they're
 // not inside the functions from objdump's point of view, an unwinder that
-// blindly looks at the previous instruction (but is then smart enough to check
-// the unwind information to find out where it landed) gets the right answer.
+// just assumes it should look at the previous instruction (but is then smart
+// enough to check the unwind information to find out where it landed) gets
+// the right answer.
 // Make sure not to have both DWARF and ARM unwind information, so only
 // use the ARM unwind information.
 
diff --git a/libc/bionic/fdsan.cpp b/libc/bionic/fdsan.cpp
index 4b89918..043510c 100644
--- a/libc/bionic/fdsan.cpp
+++ b/libc/bionic/fdsan.cpp
@@ -137,7 +137,7 @@
     return;
   }
 
-  // Lots of code will (sensibly) fork, blindly call close on all of their fds,
+  // Lots of code will (sensibly) fork, call close on all of their fds,
   // and then exec. Compare our cached pid value against the real one to detect
   // this scenario and permit it.
   pid_t cached_pid = __get_cached_pid();
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index 3814ed0..982ba95 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -56,7 +56,7 @@
 
   if (result == 0) {
     // Disable fdsan post-fork, so we don't falsely trigger on processes that
-    // fork, close all of their fds blindly, and then exec.
+    // fork, close all of their fds, and then exec.
     android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
 
     // Reset the stack_and_tls VMA name so it doesn't end with a tid from the
diff --git a/libc/bionic/ndk_cruft.cpp b/libc/bionic/ndk_cruft.cpp
index e9a5b5b..b15a317 100644
--- a/libc/bionic/ndk_cruft.cpp
+++ b/libc/bionic/ndk_cruft.cpp
@@ -55,8 +55,9 @@
 // By the time any NDK-built code is running, there are plenty of threads.
 int __isthreaded = 1;
 
-// These were accidentally declared in <unistd.h> because we stupidly used to inline
-// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
+// These were accidentally declared in <unistd.h> because we used to inline
+// getpagesize() and __getpageshift(). Needed for backwards compatibility
+// with old NDK apps.
 unsigned int __page_size = PAGE_SIZE;
 unsigned int __page_shift = 12;
 
diff --git a/libc/include/android/fdsan.h b/libc/include/android/fdsan.h
index 83b9318..e23de85 100644
--- a/libc/include/android/fdsan.h
+++ b/libc/include/android/fdsan.h
@@ -186,7 +186,8 @@
  * Set the error level and return the previous state.
  *
  * Error checking is automatically disabled in the child of a fork, to maintain
- * compatibility with code that forks, blindly closes FDs, and then execs.
+ * compatibility with code that forks, closes all file descriptors, and then
+ * execs.
  *
  * In cases such as the zygote, where the child has no intention of calling
  * exec, call this function to reenable fdsan checks.
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index ba0af3c..833fa59 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -170,6 +170,28 @@
  * Available since API level 28.
  */
 #define M_PURGE (-101)
+/**
+ * mallopt() option to set the maximum number of items in the secondary
+ * cache of the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_CACHE_COUNT_MAX (-200)
+/**
+ * mallopt() option to set the maximum size in bytes of a cacheable item in
+ * the secondary cache of the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_CACHE_SIZE_MAX (-201)
+/**
+ * mallopt() option to increase the maximum number of shared thread-specific
+ * data structures that can be created. This number cannot be decreased,
+ * only increased and only applies to the scudo allocator.
+ *
+ * Available since API level 31.
+ */
+#define M_TSDS_COUNT_MAX (-202)
 
 /**
  * [mallopt(3)](http://man7.org/linux/man-pages/man3/mallopt.3.html) modifies
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index b6a1538..8538eb0 100755
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -267,7 +267,7 @@
 
     def parseString(self, lines):
         """Parse a list of text lines into a BlockList object."""
-        file_ = 'dummy.c'
+        file_ = 'no-filename-available.c'
         self._tu = self._indexer.parse(file_, self.clang_flags,
                                        unsaved_files=[(file_, lines)],
                                        options=self.options)
diff --git a/libc/system_properties/contexts_split.cpp b/libc/system_properties/contexts_split.cpp
index 96b01a4..ccb5bcd 100644
--- a/libc/system_properties/contexts_split.cpp
+++ b/libc/system_properties/contexts_split.cpp
@@ -269,7 +269,7 @@
     if (!InitializePropertiesFromFile("/system/etc/selinux/plat_property_contexts")) {
       return false;
     }
-    // Don't check for failure here, so we always have a sane list of properties.
+    // Don't check for failure here, since we don't always have all of these partitions.
     // E.g. In case of recovery, the vendor partition will not have mounted and we
     // still need the system / platform properties to function.
     if (access("/vendor/etc/selinux/vendor_property_contexts", R_OK) != -1) {
diff --git a/libc/tools/check-symbols-glibc.py b/libc/tools/check-symbols-glibc.py
index 4de0181..d8d1982 100755
--- a/libc/tools/check-symbols-glibc.py
+++ b/libc/tools/check-symbols-glibc.py
@@ -182,9 +182,9 @@
   '_ctype_',
   '__libc_init',
 ])
-# POSIX has some stuff that's too stupid for words (a64l) or not actually
-# implemented in glibc unless you count always failing with ENOSYS as
-# being implemented (fattach). Other stuff (fmtmsg) isn't used in any
+# POSIX has some stuff that's unusable in the modern world (a64l) or not
+# actually implemented in glibc unless you count always failing with ENOSYS
+# as being implemented (fattach). Other stuff (fmtmsg) isn't used in any
 # codebase I have access to, internal or external.
 in_posix_and_glibc_but_dead_or_useless = set([
   'a64l', # obsolete
diff --git a/libc/tools/pylintrc b/libc/tools/pylintrc
deleted file mode 100644
index dd7dbf6..0000000
--- a/libc/tools/pylintrc
+++ /dev/null
@@ -1,280 +0,0 @@
-[MASTER]
-
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the ignore list. They should be base names, not
-# paths.
-ignore=CVS
-
-# Pickle collected data for later comparisons.
-persistent=yes
-
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
-[MESSAGES CONTROL]
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time. See also the "--disable" option for examples.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once).You can also use "--disable=all" to
-# disable everything first and then reenable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use"--disable=all --enable=classes
-# --disable=W"
-disable=missing-docstring,invalid-name,no-self-use,fixme,design
-
-
-[REPORTS]
-
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html. You can also give a reporter class, eg
-# mypackage.mymodule.MyReporterClass.
-output-format=text
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-reports=yes
-
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details
-#msg-template=
-
-
-[BASIC]
-
-# Required attributes for module, separated by a comma
-required-attributes=
-
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,apply,input
-
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct argument names
-argument-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct variable names
-variable-rgx=[a-z_][a-z0-9_]{2,30}$
-
-# Regular expression which should only match correct attribute names in class
-# bodies
-class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Regular expression which should only match function or class names that do
-# not require a docstring.
-no-docstring-rgx=__.*__
-
-# Minimum line length for functions/classes that require docstrings, shorter
-# ones are exempt.
-docstring-min-length=-1
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=SQLObject
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=REQUEST,acl_users,aq_parent
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-# Ignore imports when computing similarities.
-ignore-imports=no
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the beginning of the name of dummy variables
-# (i.e. not used).
-dummy-variables-rgx=_$|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-max-line-length=100
-
-# Regexp for a line that is allowed to be longer than the limit.
-ignore-long-lines=^\s*(# )?<?https?://\S+>?$
-
-# Allow the body of an if to be on the same line as the test if there is no
-# else.
-single-line-if-stmt=no
-
-# List of optional constructs for which whitespace checking is disabled
-no-space-check=trailing-comma,dict-separator
-
-# Maximum number of lines in a module
-max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-indent-string='  '
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=5
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=15
-
-# Maximum number of return / yield for function / method body
-max-returns=6
-
-# Maximum number of branch for function / method body
-max-branches=12
-
-# Maximum number of statements in function / method body
-max-statements=50
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=mcs
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c b/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
index 0468026..6e3e223 100644
--- a/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
+++ b/libc/upstream-netbsd/lib/libc/stdlib/_rand48.c
@@ -1,4 +1,4 @@
-/*	$NetBSD: _rand48.c,v 1.7 2005/06/12 05:21:27 lukem Exp $	*/
+/*	$NetBSD: _rand48.c,v 1.10 2020/02/23 09:53:42 kamil Exp $	*/
 
 /*
  * Copyright (c) 1993 Martin Birgmeier
@@ -15,7 +15,7 @@
 
 #include <sys/cdefs.h>
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: _rand48.c,v 1.7 2005/06/12 05:21:27 lukem Exp $");
+__RCSID("$NetBSD: _rand48.c,v 1.10 2020/02/23 09:53:42 kamil Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include <assert.h>
@@ -42,15 +42,17 @@
 
 	_DIAGASSERT(xseed != NULL);
 
-	accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0] +
-	 (unsigned long) __rand48_add;
+	accu = (unsigned long) __rand48_mult[0] * (unsigned long) xseed[0];
+	accu += (unsigned long) __rand48_add;
 	temp[0] = (unsigned short) accu;	/* lower 16 bits */
 	accu >>= sizeof(unsigned short) * 8;
-	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1] +
-	 (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
+	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[1];
+	accu += (unsigned long) __rand48_mult[1] * (unsigned long) xseed[0];
 	temp[1] = (unsigned short) accu;	/* middle 16 bits */
 	accu >>= sizeof(unsigned short) * 8;
-	accu += __rand48_mult[0] * xseed[2] + __rand48_mult[1] * xseed[1] + __rand48_mult[2] * xseed[0];
+	accu += (unsigned long) __rand48_mult[0] * (unsigned long) xseed[2];
+	accu += (unsigned long) __rand48_mult[1] * (unsigned long) xseed[1];
+	accu += (unsigned long) __rand48_mult[2] * (unsigned long) xseed[0];
 	xseed[0] = temp[0];
 	xseed[1] = temp[1];
 	xseed[2] = (unsigned short) accu;
diff --git a/libc/upstream-openbsd/android/include/openbsd-compat.h b/libc/upstream-openbsd/android/include/openbsd-compat.h
index 8206269..2fc5046 100644
--- a/libc/upstream-openbsd/android/include/openbsd-compat.h
+++ b/libc/upstream-openbsd/android/include/openbsd-compat.h
@@ -72,3 +72,7 @@
 
 __LIBC_HIDDEN__ extern char* __findenv(const char*, int, int*);
 __LIBC_HIDDEN__ extern char* _mktemp(char*);
+
+// Only OpenBSD has this at the moment, and we're more likely to just say
+// "malloc is always calloc", so we don't expose this as libc API.
+__LIBC_HIDDEN__ void* recallocarray(void*, size_t, size_t, size_t);
diff --git a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
index 0d0f18f..d7afd5f 100644
--- a/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
+++ b/libc/upstream-openbsd/lib/libc/gen/fnmatch.c
@@ -1,8 +1,8 @@
-/*	$OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $	*/
+/*	$OpenBSD: fnmatch.c,v 1.22 2020/03/13 03:25:45 djm Exp $	*/
 
 /* Copyright (c) 2011, VMware, Inc.
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
  *     * Redistributions of source code must retain the above copyright
@@ -13,7 +13,7 @@
  *     * Neither the name of the VMware, Inc. 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 COPYRIGHT HOLDERS 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
@@ -27,7 +27,7 @@
  */
 
 /*
- * Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
+ * Copyright (c) 2008, 2016 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -51,9 +51,9 @@
  * Filename pattern matches defined in section 2.13, "Pattern Matching Notation"
  * from chapter 2. "Shell Command Language"
  *   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13
- * where; 1. A bracket expression starting with an unquoted <circumflex> '^' 
- * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.' 
- * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading 
+ * where; 1. A bracket expression starting with an unquoted <circumflex> '^'
+ * character CONTINUES to specify a non-matching list; 2. an explicit <period> '.'
+ * in a bracket expression matching list, e.g. "[.abc]" does NOT match a leading
  * <period> in a filename; 3. a <left-square-bracket> '[' which does not introduce
  * a valid bracket expression is treated as an ordinary character; 4. a differing
  * number of consecutive slashes within pattern and string will NOT match;
@@ -62,10 +62,10 @@
  * Bracket expansion defined in section 9.3.5, "RE Bracket Expression",
  * from chapter 9, "Regular Expressions"
  *   http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03_05
- * with no support for collating symbols, equivalence class expressions or 
- * character class expressions.  A partial range expression with a leading 
+ * with no support for collating symbols, equivalence class expressions or
+ * character class expressions.  A partial range expression with a leading
  * hyphen following a valid range expression will match only the ordinary
- * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters 
+ * <hyphen> and the ending character (e.g. "[a-m-z]" will match characters
  * 'a' through 'm', a <hyphen> '-', or a 'z').
  *
  * Supports BSD extensions FNM_LEADING_DIR to match pattern to the end of one
@@ -98,22 +98,21 @@
 static int
 classmatch(const char *pattern, char test, int foldcase, const char **ep)
 {
-	struct cclass *cc;
-	const char *colon;
-	size_t len;
-	int rval = RANGE_NOMATCH;
 	const char * const mismatch = pattern;
+	const char *colon;
+	struct cclass *cc;
+	int rval = RANGE_NOMATCH;
+	size_t len;
 
-	if (*pattern != '[' || pattern[1] != ':') {
+	if (pattern[0] != '[' || pattern[1] != ':') {
 		*ep = mismatch;
-		return(RANGE_ERROR);
+		return RANGE_ERROR;
 	}
-
 	pattern += 2;
 
 	if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
 		*ep = mismatch;
-		return(RANGE_ERROR);
+		return RANGE_ERROR;
 	}
 	*ep = colon + 2;
 	len = (size_t)(colon - pattern);
@@ -132,11 +131,11 @@
 		*ep = mismatch;
 		rval = RANGE_ERROR;
 	}
-	return(rval);
+	return rval;
 }
 
 /* Most MBCS/collation/case issues handled here.  Wildcard '*' is not handled.
- * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over, 
+ * EOS '\0' and the FNM_PATHNAME '/' delimiters are not advanced over,
  * however the "\/" sequence is advanced to '/'.
  *
  * Both pattern and string are **char to support pointer increment of arbitrary
@@ -144,341 +143,347 @@
  */
 static int fnmatch_ch(const char **pattern, const char **string, int flags)
 {
-    const char * const mismatch = *pattern;
-    const int nocase = !!(flags & FNM_CASEFOLD);
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int slash = !!(flags & FNM_PATHNAME);
-    int result = FNM_NOMATCH;
-    const char *startch;
-    int negate;
+	const char * const mismatch = *pattern;
+	const int nocase = !!(flags & FNM_CASEFOLD);
+	const int escape = !(flags & FNM_NOESCAPE);
+	const int slash = !!(flags & FNM_PATHNAME);
+	int result = FNM_NOMATCH;
+	const char *startch;
+	int negate;
 
-    if (**pattern == '[')
-    {
-        ++*pattern;
+	if (**pattern == '[') {
+		++*pattern;
 
-        /* Handle negation, either leading ! or ^ operators (never both) */
-        negate = ((**pattern == '!') || (**pattern == '^'));
-        if (negate)
-            ++*pattern;
+		/* Handle negation, either leading ! or ^ operators */
+		negate = (**pattern == '!') || (**pattern == '^');
+		if (negate)
+			++*pattern;
 
-        /* ']' is an ordinary character at the start of the range pattern */
-        if (**pattern == ']')
-            goto leadingclosebrace;
+		/* ']' is an ordinary char at the start of the range pattern */
+		if (**pattern == ']')
+			goto leadingclosebrace;
 
-        while (**pattern)
-        {
-            if (**pattern == ']') {
-                ++*pattern;
-                /* XXX: Fix for MBCS character width */
-                ++*string;
-                return (result ^ negate);
-            }
+		while (**pattern) {
+			if (**pattern == ']') {
+				++*pattern;
+				/* XXX: Fix for MBCS character width */
+				++*string;
+				return (result ^ negate);
+			}
 
-            if (escape && (**pattern == '\\')) {
-                ++*pattern;
+			if (escape && (**pattern == '\\')) {
+				++*pattern;
 
-                /* Patterns must be terminated with ']', not EOS */
-                if (!**pattern)
-                    break;
-            }
+				/* Patterns must terminate with ']', not EOS */
+				if (!**pattern)
+					break;
+			}
 
-            /* Patterns must be terminated with ']' not '/' */
-            if (slash && (**pattern == '/'))
-                break;
+			/* Patterns must terminate with ']' not '/' */
+			if (slash && (**pattern == '/'))
+				break;
 
-            /* Match character classes. */
-            if (classmatch(*pattern, **string, nocase, pattern)
-                == RANGE_MATCH) {
-                result = 0;
-                continue;
-            }
-            if (!**pattern)
-                break;
+			/* Match character classes. */
+			switch (classmatch(*pattern, **string, nocase, pattern)) {
+			case RANGE_MATCH:
+				result = 0;
+				continue;
+			case RANGE_NOMATCH:
+				/* Valid character class but no match. */
+				continue;
+			default:
+				/* Not a valid character class. */
+				break;
+			}
+			if (!**pattern)
+				break;
 
 leadingclosebrace:
-            /* Look at only well-formed range patterns; 
-             * "x-]" is not allowed unless escaped ("x-\]")
-             * XXX: Fix for locale/MBCS character width
-             */
-            if (((*pattern)[1] == '-') && ((*pattern)[2] != ']'))
-            {
-                startch = *pattern;
-                *pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
+			/* Look at only well-formed range patterns;
+			 * "x-]" is not allowed unless escaped ("x-\]")
+			 * XXX: Fix for locale/MBCS character width
+			 */
+			if (((*pattern)[1] == '-') && ((*pattern)[2] != ']')) {
+				startch = *pattern;
+				*pattern += (escape && ((*pattern)[2] == '\\')) ? 3 : 2;
 
-                /* NOT a properly balanced [expr] pattern, EOS terminated 
-                 * or ranges containing a slash in FNM_PATHNAME mode pattern
-                 * fall out to to the rewind and test '[' literal code path
-                 */
-                if (!**pattern || (slash && (**pattern == '/')))
-                    break;
+				/*
+				 * NOT a properly balanced [expr] pattern, EOS
+				 * terminated or ranges containing a slash in
+				 * FNM_PATHNAME mode pattern fall out to to the
+				 * rewind and test '[' literal code path.
+				 */
+				if (!**pattern || (slash && (**pattern == '/')))
+					break;
 
-                /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
-                if ((**string >= *startch) && (**string <= **pattern))
-                    result = 0;
-                else if (nocase && (isupper((unsigned char)**string) ||
-			    isupper((unsigned char)*startch) ||
-                            isupper((unsigned char)**pattern))
-                            && (tolower((unsigned char)**string) >=
-			        tolower((unsigned char)*startch)) 
-                            && (tolower((unsigned char)**string) <=
-				tolower((unsigned char)**pattern)))
-                    result = 0;
+				/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+				if ((**string >= *startch) && (**string <= **pattern))
+					result = 0;
+				else if (nocase &&
+				    (isupper((unsigned char)**string) ||
+				     isupper((unsigned char)*startch) ||
+				     isupper((unsigned char)**pattern)) &&
+				    (tolower((unsigned char)**string) >=
+				     tolower((unsigned char)*startch)) &&
+				    (tolower((unsigned char)**string) <=
+				     tolower((unsigned char)**pattern)))
+					result = 0;
 
-                ++*pattern;
-                continue;
-            }
+				++*pattern;
+				continue;
+			}
 
-            /* XXX: handle locale/MBCS comparison, advance by MBCS char width */
-            if ((**string == **pattern))
-                result = 0;
-            else if (nocase && (isupper((unsigned char)**string) ||
-			    isupper((unsigned char)**pattern))
-                            && (tolower((unsigned char)**string) ==
-				tolower((unsigned char)**pattern)))
-                result = 0;
+			/* XXX: handle locale/MBCS comparison, advance by MBCS char width */
+			if ((**string == **pattern))
+				result = 0;
+			else if (nocase && (isupper((unsigned char)**string) ||
+			    isupper((unsigned char)**pattern)) &&
+			    (tolower((unsigned char)**string) ==
+			    tolower((unsigned char)**pattern)))
+				result = 0;
 
-            ++*pattern;
-        }
+			++*pattern;
+		}
+		/*
+		 * NOT a properly balanced [expr] pattern;
+		 * Rewind and reset result to test '[' literal
+		 */
+		*pattern = mismatch;
+		result = FNM_NOMATCH;
+	} else if (**pattern == '?') {
+		/* Optimize '?' match before unescaping **pattern */
+		if (!**string || (slash && (**string == '/')))
+			return FNM_NOMATCH;
+		result = 0;
+		goto fnmatch_ch_success;
+	} else if (escape && (**pattern == '\\') && (*pattern)[1]) {
+		++*pattern;
+	}
 
-        /* NOT a properly balanced [expr] pattern; Rewind
-         * and reset result to test '[' literal
-         */
-        *pattern = mismatch;
-        result = FNM_NOMATCH;
-    }
-    else if (**pattern == '?') {
-        /* Optimize '?' match before unescaping **pattern */
-        if (!**string || (slash && (**string == '/')))
-            return FNM_NOMATCH;
-        result = 0;
-        goto fnmatch_ch_success;
-    }
-    else if (escape && (**pattern == '\\') && (*pattern)[1]) {
-        ++*pattern;
-    }
+	/* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
+	if (**string == **pattern)
+		result = 0;
+	else if (nocase && (isupper((unsigned char)**string) ||
+	    isupper((unsigned char)**pattern)) &&
+	    (tolower((unsigned char)**string) ==
+	    tolower((unsigned char)**pattern)))
+		result = 0;
 
-    /* XXX: handle locale/MBCS comparison, advance by the MBCS char width */
-    if (**string == **pattern)
-        result = 0;
-    else if (nocase && (isupper((unsigned char)**string) ||
-		    isupper((unsigned char)**pattern))
-                    && (tolower((unsigned char)**string) ==
-			tolower((unsigned char)**pattern)))
-        result = 0;
-
-    /* Refuse to advance over trailing slash or nulls
-     */
-    if (!**string || !**pattern || (slash && ((**string == '/') || (**pattern == '/'))))
-        return result;
+	/* Refuse to advance over trailing slash or NULs */
+	if (**string == '\0' || **pattern == '\0' ||
+	    (slash && ((**string == '/') || (**pattern == '/'))))
+		return result;
 
 fnmatch_ch_success:
-    ++*pattern;
-    ++*string;
-    return result;
+	++*pattern;
+	++*string;
+	return result;
 }
 
 
 int fnmatch(const char *pattern, const char *string, int flags)
 {
-    static const char dummystring[2] = {' ', 0};
-    const int escape = !(flags & FNM_NOESCAPE);
-    const int slash = !!(flags & FNM_PATHNAME);
-    const int leading_dir = !!(flags & FNM_LEADING_DIR);
-    const char *strendseg;
-    const char *dummyptr;
-    const char *matchptr;
-    int wild;
-    /* For '*' wild processing only; surpress 'used before initialization'
-     * warnings with dummy initialization values;
-     */
-    const char *strstartseg = NULL;
-    const char *mismatch = NULL;
-    int matchlen = 0;
+	static const char dummystring[2] = {' ', 0};
+	const int escape = !(flags & FNM_NOESCAPE);
+	const int slash = !!(flags & FNM_PATHNAME);
+	const int leading_dir = !!(flags & FNM_LEADING_DIR);
+	const char *dummyptr, *matchptr, *strendseg;
+	int wild;
+	/* For '*' wild processing only; suppress 'used before initialization'
+	 * warnings with dummy initialization values;
+	 */
+	const char *strstartseg = NULL;
+	const char *mismatch = NULL;
+	int matchlen = 0;
 
-    if (*pattern == '*')
-        goto firstsegment;
+	if (*pattern == '*')
+		goto firstsegment;
 
-    while (*pattern && *string)
-    {
-        /* Pre-decode "\/" which has no special significance, and
-         * match balanced slashes, starting a new segment pattern
-         */
-        if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
-            ++pattern;
-        if (slash && (*pattern == '/') && (*string == '/')) {
-            ++pattern;
-            ++string;
-        }            
+	while (*pattern && *string) {
+		/*
+		 * Pre-decode "\/" which has no special significance, and
+		 * match balanced slashes, starting a new segment pattern.
+		 */
+		if (slash && escape && (*pattern == '\\') && (pattern[1] == '/'))
+			++pattern;
+		if (slash && (*pattern == '/') && (*string == '/')) {
+			++pattern;
+			++string;
+		}
 
 firstsegment:
-        /* At the beginning of each segment, validate leading period behavior.
-         */
-        if ((flags & FNM_PERIOD) && (*string == '.'))
-        {
-            if (*pattern == '.')
-                ++pattern;
-            else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
-                pattern += 2;
-            else
-                return FNM_NOMATCH;
-            ++string;
-        }
+		/*
+		 * At the beginning of each segment, validate leading period
+		 * behavior.
+		 */
+		if ((flags & FNM_PERIOD) && (*string == '.')) {
+		    if (*pattern == '.')
+			    ++pattern;
+		    else if (escape && (*pattern == '\\') && (pattern[1] == '.'))
+			    pattern += 2;
+		    else
+			    return FNM_NOMATCH;
+		    ++string;
+		}
 
-        /* Determine the end of string segment
-         *
-         * Presumes '/' character is unique, not composite in any MBCS encoding
-         */
-        if (slash) {
-            strendseg = strchr(string, '/');
-            if (!strendseg)
-                strendseg = strchr(string, '\0');
-        }
-        else {
-            strendseg = strchr(string, '\0');
-        }
+		/*
+		 * Determine the end of string segment.  Presumes '/'
+		 * character is unique, not composite in any MBCS encoding
+		 */
+		if (slash) {
+			strendseg = strchr(string, '/');
+			if (!strendseg)
+				strendseg = strchr(string, '\0');
+		} else {
+			strendseg = strchr(string, '\0');
+		}
 
-        /* Allow pattern '*' to be consumed even with no remaining string to match
-         */
-        while (*pattern)
-        {
-            if ((string > strendseg)
-                || ((string == strendseg) && (*pattern != '*')))
-                break;
+		/*
+		 * Allow pattern '*' to be consumed even with no remaining
+		 * string to match.
+		 */
+		while (*pattern) {
+			if ((string > strendseg) ||
+			    ((string == strendseg) && (*pattern != '*')))
+				break;
 
-            if (slash && ((*pattern == '/')
-                           || (escape && (*pattern == '\\')
-                                      && (pattern[1] == '/'))))
-                break;
+			if (slash && ((*pattern == '/') ||
+			    (escape && (*pattern == '\\') && (pattern[1] == '/'))))
+				break;
 
-            /* Reduce groups of '*' and '?' to n '?' matches
-             * followed by one '*' test for simplicity
-             */
-            for (wild = 0; ((*pattern == '*') || (*pattern == '?')); ++pattern)
-            {
-                if (*pattern == '*') {
-                    wild = 1;
-                }
-                else if (string < strendseg) {  /* && (*pattern == '?') */
-                    /* XXX: Advance 1 char for MBCS locale */
-                    ++string;
-                }
-                else {  /* (string >= strendseg) && (*pattern == '?') */
-                    return FNM_NOMATCH;
-                }
-            }
+			/*
+			 * Reduce groups of '*' and '?' to n '?' matches
+			 * followed by one '*' test for simplicity.
+			 */
+			for (wild = 0; (*pattern == '*') || (*pattern == '?'); ++pattern) {
+				if (*pattern == '*') {
+					wild = 1;
+				} else if (string < strendseg) {  /* && (*pattern == '?') */
+					/* XXX: Advance 1 char for MBCS locale */
+					++string;
+				}
+				else {  /* (string >= strendseg) && (*pattern == '?') */
+					return FNM_NOMATCH;
+				}
+			}
 
-            if (wild)
-            {
-                strstartseg = string;
-                mismatch = pattern;
+			if (wild) {
+				strstartseg = string;
+				mismatch = pattern;
 
-                /* Count fixed (non '*') char matches remaining in pattern
-                 * excluding '/' (or "\/") and '*'
-                 */
-                for (matchptr = pattern, matchlen = 0; 1; ++matchlen)
-                {
-                    if ((*matchptr == '\0') 
-                        || (slash && ((*matchptr == '/')
-                                      || (escape && (*matchptr == '\\')
-                                                 && (matchptr[1] == '/')))))
-                    {
-                        /* Compare precisely this many trailing string chars,
-                         * the resulting match needs no wildcard loop
-                         */
-                        /* XXX: Adjust for MBCS */
-                        if (string + matchlen > strendseg)
-                            return FNM_NOMATCH;
+				/*
+				 * Count fixed (non '*') char matches remaining
+				 * in pattern * excluding '/' (or "\/") and '*'.
+				 */
+				for (matchptr = pattern, matchlen = 0; 1; ++matchlen) {
+					if ((*matchptr == '\0') ||
+					    (slash && ((*matchptr == '/') ||
+					    (escape && (*matchptr == '\\') &&
+					    (matchptr[1] == '/'))))) {
+						/* Compare precisely this many
+						 * trailing string chars, the
+						 * resulting match needs no
+						 * wildcard loop.
+						 */
+						/* XXX: Adjust for MBCS */
+						if (string + matchlen > strendseg)
+							return FNM_NOMATCH;
 
-                        string = strendseg - matchlen;
-                        wild = 0;
-                        break;
-                    }
+						string = strendseg - matchlen;
+						wild = 0;
+						break;
+					}
 
-                    if (*matchptr == '*')
-                    {
-                        /* Ensure at least this many trailing string chars remain
-                         * for the first comparison
-                         */
-                        /* XXX: Adjust for MBCS */
-                        if (string + matchlen > strendseg)
-                            return FNM_NOMATCH;
+					if (*matchptr == '*') {
+						/*
+						 * Ensure at least this many
+						 * trailing string chars remain
+						 * for the first comparison.
+						 */
+						/* XXX: Adjust for MBCS */
+						if (string + matchlen > strendseg)
+							return FNM_NOMATCH;
 
-                        /* Begin first wild comparison at the current position */
-                        break;
-                    }
+						/*
+						 * Begin first wild comparison
+						 * at the current position.
+						 */
+						break;
+					}
 
-                    /* Skip forward in pattern by a single character match
-                     * Use a dummy fnmatch_ch() test to count one "[range]" escape
-                     */ 
-                    /* XXX: Adjust for MBCS */
-                    if (escape && (*matchptr == '\\') && matchptr[1]) {
-                        matchptr += 2;
-                    }
-                    else if (*matchptr == '[') {
-                        dummyptr = dummystring;
-                        fnmatch_ch(&matchptr, &dummyptr, flags);
-                    }
-                    else {
-                        ++matchptr;
-                    }
-                }
-            }
+					/*
+					 * Skip forward in pattern by a single
+					 * character match Use a dummy
+					 * fnmatch_ch() test to count one
+					 * "[range]" escape.
+					 */
+					/* XXX: Adjust for MBCS */
+					if (escape && (*matchptr == '\\') &&
+					    matchptr[1]) {
+						matchptr += 2;
+					} else if (*matchptr == '[') {
+						dummyptr = dummystring;
+						fnmatch_ch(&matchptr, &dummyptr,
+						    flags);
+					} else {
+						++matchptr;
+					}
+				}
+			}
 
-            /* Incrementally match string against the pattern
-             */
-            while (*pattern && (string < strendseg))
-            {
-                /* Success; begin a new wild pattern search
-                 */
-                if (*pattern == '*')
-                    break;
+			/* Incrementally match string against the pattern. */
+			while (*pattern && (string < strendseg)) {
+				/* Success; begin a new wild pattern search. */
+				if (*pattern == '*')
+					break;
 
-                if (slash && ((*string == '/')
-                              || (*pattern == '/')
-                              || (escape && (*pattern == '\\')
-                                         && (pattern[1] == '/'))))
-                    break;
+				if (slash && ((*string == '/') ||
+				    (*pattern == '/') || (escape &&
+				    (*pattern == '\\') && (pattern[1] == '/'))))
+					break;
 
-                /* Compare ch's (the pattern is advanced over "\/" to the '/',
-                 * but slashes will mismatch, and are not consumed)
-                 */
-                if (!fnmatch_ch(&pattern, &string, flags))
-                    continue;
+				/*
+				 * Compare ch's (the pattern is advanced over
+				 * "\/" to the '/', but slashes will mismatch,
+				 * and are not consumed).
+				 */
+				if (!fnmatch_ch(&pattern, &string, flags))
+					continue;
 
-                /* Failed to match, loop against next char offset of string segment 
-                 * until not enough string chars remain to match the fixed pattern
-                 */
-                if (wild) {
-                    /* XXX: Advance 1 char for MBCS locale */
-                    string = ++strstartseg;
-                    if (string + matchlen > strendseg)
-                        return FNM_NOMATCH;
+				/*
+				 * Failed to match, loop against next char
+				 * offset of string segment until not enough
+				 * string chars remain to match the fixed
+				 * pattern.
+				 */
+				if (wild) {
+					/* XXX: Advance 1 char for MBCS locale */
+					string = ++strstartseg;
+					if (string + matchlen > strendseg)
+						return FNM_NOMATCH;
 
-                    pattern = mismatch;
-                    continue;
-                }
-                else
-                    return FNM_NOMATCH;
-            }
-        }
+					pattern = mismatch;
+					continue;
+				} else
+					return FNM_NOMATCH;
+			}
+		}
 
-        if (*string && !((slash || leading_dir) && (*string == '/')))
-            return FNM_NOMATCH;
+		if (*string && !((slash || leading_dir) && (*string == '/')))
+			return FNM_NOMATCH;
 
-        if (*pattern && !(slash && ((*pattern == '/')
-                                    || (escape && (*pattern == '\\')
-                                               && (pattern[1] == '/')))))
-            return FNM_NOMATCH;
+		if (*pattern && !(slash && ((*pattern == '/') ||
+		    (escape && (*pattern == '\\') && (pattern[1] == '/')))))
+			return FNM_NOMATCH;
 
-        if (leading_dir && !*pattern && *string == '/')
-            return 0;
-    }
+		if (leading_dir && !*pattern && *string == '/')
+			return 0;
+	}
 
-    /* Where both pattern and string are at EOS, declare success
-     */
-    if (!*string && !*pattern)
-        return 0;
+	/* Where both pattern and string are at EOS, declare success.  */
+	if (!*string && !*pattern)
+		return 0;
 
-    /* pattern didn't match to the end of string */
-    return FNM_NOMATCH;
+	/* Pattern didn't match to the end of string. */
+	return FNM_NOMATCH;
 }
diff --git a/libc/upstream-openbsd/lib/libc/locale/mbtowc.c b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
index 920f4bf..4399ed8 100644
--- a/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
+++ b/libc/upstream-openbsd/lib/libc/locale/mbtowc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: mbtowc.c,v 1.2 2012/12/05 23:20:00 deraadt Exp $ */
+/*	$OpenBSD: mbtowc.c,v 1.3 2016/02/27 14:02:13 schwarze Exp $ */
 
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
@@ -44,7 +44,14 @@
 		return (0);
 	}
 	rval = mbrtowc(pwc, s, n, &mbs);
-	if (rval == (size_t)-1 || rval == (size_t)-2)
-		return (-1);
-	return ((int)rval);
+
+	switch (rval) {
+	case (size_t)-2:
+		errno = EILSEQ;
+		/* FALLTHROUGH */
+	case (size_t)-1:
+		return -1;
+	default:
+		return (int)rval;
+	}
 }
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
index 1109cf2..903dbd6 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fgetln.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fgetln.c,v 1.13 2015/01/05 21:58:52 millert Exp $ */
+/*	$OpenBSD: fgetln.c,v 1.17 2017/03/17 14:53:08 deraadt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -46,7 +46,7 @@
 
 	if (fp->_lb._size >= newsize)
 		return (0);
-	if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+	if ((p = recallocarray(fp->_lb._base, fp->_lb._size, newsize, 1)) == NULL)
 		return (-1);
 	fp->_lb._base = p;
 	fp->_lb._size = newsize;
@@ -76,7 +76,7 @@
 		goto error;
 
 	/* look for a newline in the input */
-	if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+	if ((p = memchr(fp->_p, '\n', fp->_r)) != NULL) {
 		/*
 		 * Found one.  Flag buffer as modified to keep fseek from
 		 * `optimising' a backward seek, in case the user stomps on
@@ -112,12 +112,14 @@
 		 */
 		if (__slbexpand(fp, len + OPTIMISTIC))
 			goto error;
-		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
-		    len - off);
+		(void)memcpy(fp->_lb._base + off, fp->_p, len - off);
 		off = len;
-		if (__srefill(fp))
-			break;	/* EOF or error: return partial line */
-		if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+		if (__srefill(fp)) {
+			if (fp->_flags & __SEOF)
+				break;
+			goto error;
+		}
+		if ((p = memchr(fp->_p, '\n', fp->_r)) == NULL)
 			continue;
 
 		/* got it: finish up the line (like code above) */
@@ -126,8 +128,7 @@
 		len += diff;
 		if (__slbexpand(fp, len))
 			goto error;
-		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
-		    diff);
+		(void)memcpy(fp->_lb._base + off, fp->_p, diff);
 		fp->_r -= diff;
 		fp->_p = p;
 		break;
@@ -142,3 +143,4 @@
 	*lenp = 0;
 	return (NULL);
 }
+DEF_WEAK(fgetln);
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fputwc.c b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
index 829c22c..e156922 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fputwc.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fputwc.c,v 1.6 2015/10/01 02:32:07 guenther Exp $	*/
+/*	$OpenBSD: fputwc.c,v 1.7 2016/01/26 13:57:02 schwarze Exp $	*/
 /* $NetBSD: fputwc.c,v 1.3 2003/03/07 07:11:37 tshiozak Exp $ */
 
 /*-
@@ -62,7 +62,7 @@
 
 	size = wcrtomb(buf, wc, st);
 	if (size == (size_t)-1) {
-		errno = EILSEQ;
+		fp->_flags |= __SERR;
 		return WEOF;
 	}
 
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
index 1088991..ba58f9d 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
+/*	$OpenBSD: fvwrite.c,v 1.20 2017/03/17 16:06:33 millert Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 #include "local.h"
 #include "fvwrite.h"
 
@@ -63,7 +64,7 @@
 	}
 
 #define	MIN(a, b) ((a) < (b) ? (a) : (b))
-#define	COPY(n)	  (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+#define	COPY(n)	  (void)memcpy(fp->_p, p, n)
 
 	iov = uio->uio_iov;
 	p = iov->iov_base;
@@ -105,15 +106,14 @@
 			if ((fp->_flags & (__SALC | __SSTR)) ==
 			    (__SALC | __SSTR) && fp->_w < len) {
 				size_t blen = fp->_p - fp->_bf._base;
+				int pgmsk = getpagesize() - 1;
 				unsigned char *_base;
 				int _size;
 
-				/* Allocate space exponentially. */
-				_size = fp->_bf._size;
-				do {
-					_size = (_size << 1) + 1;
-				} while (_size < blen + len);
-				_base = realloc(fp->_bf._base, _size + 1);
+				/* Round up to nearest page. */
+				_size = ((blen + len + 1 + pgmsk) & ~pgmsk) - 1;
+				_base = recallocarray(fp->_bf._base,
+				    fp->_bf._size + 1, _size + 1, 1);
 				if (_base == NULL)
 					goto err;
 				fp->_w += _size - fp->_bf._size;
@@ -164,7 +164,7 @@
 		do {
 			GETIOV(nlknown = 0);
 			if (!nlknown) {
-				nl = memchr((void *)p, '\n', len);
+				nl = memchr(p, '\n', len);
 				nldist = nl ? nl + 1 - p : len + 1;
 				nlknown = 1;
 			}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fwide.c b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
index 27ca0f8..4b93d59 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/fwide.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fwide.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fwide.c,v 1.5 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: fwide.c,v 1.6 2019/12/03 05:03:37 asou Exp $	*/
 /* $NetBSD: fwide.c,v 1.2 2003/01/18 11:29:54 thorpej Exp $ */
 
 /*-
@@ -51,8 +51,10 @@
 
 	FLOCKFILE(fp);
 	wcio = WCIO_GET(fp);
-	if (!wcio)
+	if (!wcio) {
+		FUNLOCKFILE(fp);
 		return 0; /* XXX */
+	}
 
 	if (wcio->wcio_mode == 0 && mode != 0)
 		wcio->wcio_mode = mode;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/getdelim.c b/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
index 58ff0a1..d709a3d 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/getdelim.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: getdelim.c,v 1.4 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: getdelim.c,v 1.6 2017/04/13 18:36:51 brynet Exp $	*/
 /* $NetBSD: getdelim.c,v 1.13 2011/07/22 23:12:30 joerg Exp $ */
 
 /*
@@ -73,7 +73,7 @@
 		}
 
 		/* Scan through looking for the separator */
-		p = memchr(fp->_p, sep, (size_t)fp->_r);
+		p = memchr(fp->_p, sep, fp->_r);
 		if (p == NULL)
 			len = fp->_r;
 		else
@@ -103,7 +103,7 @@
 				newlen++;
 			}
 
-			newb = realloc(*buf, newlen);
+			newb = recallocarray(*buf, *buflen, newlen, 1);
 			if (newb == NULL)
 				goto error;
 			*buf = newb;
diff --git a/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
index f708acc..6ee5a5c 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/open_memstream.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: open_memstream.c,v 1.6 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: open_memstream.c,v 1.8 2019/05/02 08:30:10 yasuoka Exp $	*/
 
 /*
  * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
@@ -50,7 +50,7 @@
 
 		if (sz < end + 1)
 			sz = end + 1;
-		p = realloc(st->string, sz);
+		p = recallocarray(st->string, st->size, sz, 1);
 		if (!p)
 			return (-1);
 		bzero(p + st->size, sz - st->size);
@@ -76,7 +76,7 @@
 memstream_seek(void *v, fpos_t off, int whence)
 {
 	struct state	*st = v;
-	ssize_t		 base = 0;
+	size_t		 base = 0;
 
 	switch (whence) {
 	case SEEK_SET:
@@ -89,7 +89,7 @@
 		break;
 	}
 
-	if (off > SIZE_MAX - base || off < -base) {
+	if ((off > 0 && off > SIZE_MAX - base) || (off < 0 && base < -off)) {
 		errno = EOVERFLOW;
 		return (-1);
 	}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
index 98cdb45..c2e17e7 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vasprintf.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: vasprintf.c,v 1.19 2015/12/28 22:08:18 mmcc Exp $	*/
+/*	$OpenBSD: vasprintf.c,v 1.23 2019/01/25 00:19:25 millert Exp $	*/
 
 /*
- * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1997 Todd C. Miller <millert@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -20,31 +20,40 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 #include "local.h"
 
+#define	INITIAL_SIZE	128
+
 int
 vasprintf(char **str, const char *fmt, __va_list ap)
 {
 	int ret;
 	FILE f;
 	struct __sfileext fext;
-	unsigned char *_base;
+	const int pgsz = getpagesize();
 
 	_FILEEXT_SETUP(&f, &fext);
 	f._file = -1;
 	f._flags = __SWR | __SSTR | __SALC;
-	f._bf._base = f._p = malloc(128);
+	f._bf._base = f._p = malloc(INITIAL_SIZE);
 	if (f._bf._base == NULL)
 		goto err;
-	f._bf._size = f._w = 127;		/* Leave room for the NUL */
+	f._bf._size = f._w = INITIAL_SIZE - 1;	/* leave room for the NUL */
 	ret = __vfprintf(&f, fmt, ap);
 	if (ret == -1)
 		goto err;
 	*f._p = '\0';
-	_base = realloc(f._bf._base, ret + 1);
-	if (_base == NULL)
-		goto err;
-	*str = (char *)_base;
+	if (ret + 1 > INITIAL_SIZE && ret + 1 < pgsz / 2) {
+		/* midsize allocations can try to conserve memory */
+		unsigned char *_base = recallocarray(f._bf._base,
+		    f._bf._size + 1, ret + 1, 1);
+
+		if (_base == NULL)
+			goto err;
+		*str = (char *)_base;
+	} else
+		*str = (char *)f._bf._base;
 	return (ret);
 
 err:
diff --git a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
index e76fcd4..ad4ab0a 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/vdprintf.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: vdprintf.c,v 1.2 2015/08/31 02:53:57 guenther Exp $	*/
+/*	$OpenBSD: vdprintf.c,v 1.3 2019/03/03 16:41:41 semarie Exp $	*/
 /*	$FreeBSD: src/lib/libc/stdio/vdprintf.c,v 1.4 2012/11/17 01:49:40 svnexp Exp $ */
 
 /*-
@@ -69,6 +69,6 @@
 	if ((ret = __vfprintf(&f, fmt, ap)) < 0)
 		return ret;
 
-	return fflush(&f) ? EOF : ret;
+	return __sflush(&f) ? EOF : ret;
 }
 DEF_WEAK(vdprintf);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
new file mode 100644
index 0000000..a2f37fe
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdlib/recallocarray.c
@@ -0,0 +1,81 @@
+/*	$OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $	*/
+/*
+ * Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+	size_t oldsize, newsize;
+	void *newptr;
+
+	if (ptr == NULL)
+		return calloc(newnmemb, size);
+
+	if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	newsize = newnmemb * size;
+
+	if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+		errno = EINVAL;
+		return NULL;
+	}
+	oldsize = oldnmemb * size;
+	
+	/*
+	 * Don't bother too much if we're shrinking just a bit,
+	 * we do not shrink for series of small steps, oh well.
+	 */
+	if (newsize <= oldsize) {
+		size_t d = oldsize - newsize;
+
+		if (d < oldsize / 2 && d < getpagesize()) {
+			memset((char *)ptr + newsize, 0, d);
+			return ptr;
+		}
+	}
+
+	newptr = malloc(newsize);
+	if (newptr == NULL)
+		return NULL;
+
+	if (newsize > oldsize) {
+		memcpy(newptr, ptr, oldsize);
+		memset((char *)newptr + oldsize, 0, newsize - oldsize);
+	} else
+		memcpy(newptr, ptr, newsize);
+
+	explicit_bzero(ptr, oldsize);
+	free(ptr);
+
+	return newptr;
+}
+DEF_WEAK(recallocarray);
diff --git a/libc/upstream-openbsd/lib/libc/stdlib/setenv.c b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
index e55a1fe..15c550b 100644
--- a/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
+++ b/libc/upstream-openbsd/lib/libc/stdlib/setenv.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: setenv.c,v 1.16 2015/09/13 08:31:47 guenther Exp $ */
+/*	$OpenBSD: setenv.c,v 1.19 2016/09/21 04:38:56 guenther Exp $ */
 /*
  * Copyright (c) 1987 Regents of the University of California.
  * All rights reserved.
@@ -32,7 +32,6 @@
 #include <stdlib.h>
 #include <string.h>
 
-extern char **environ;
 static char **lastenv;				/* last value of environ */
 
 /*
@@ -44,7 +43,7 @@
 putenv(char *str)
 {
 	char **P, *cp;
-	size_t cnt;
+	size_t cnt = 0;
 	int offset = 0;
 
 	for (cp = str; *cp && *cp != '='; ++cp)
@@ -66,13 +65,15 @@
 	}
 
 	/* create new slot for string */
-	for (P = environ; *P != NULL; P++)
-		;
-	cnt = P - environ;
+	if (environ != NULL) {
+		for (P = environ; *P != NULL; P++)
+			;
+		cnt = P - environ;
+	}
 	P = reallocarray(lastenv, cnt + 2, sizeof(char *));
 	if (!P)
 		return (-1);
-	if (lastenv != environ)
+	if (lastenv != environ && environ != NULL)
 		memcpy(P, environ, cnt * sizeof(char *));
 	lastenv = environ = P;
 	environ[cnt] = str;
@@ -123,22 +124,24 @@
 					break;
 		}
 	} else {					/* create new slot */
-		size_t cnt;
+		size_t cnt = 0;
 
-		for (P = environ; *P != NULL; P++)
-			;
-		cnt = P - environ;
+		if (environ != NULL) {
+			for (P = environ; *P != NULL; P++)
+				;
+			cnt = P - environ;
+		}
 		P = reallocarray(lastenv, cnt + 2, sizeof(char *));
 		if (!P)
 			return (-1);
-		if (lastenv != environ)
+		if (lastenv != environ && environ != NULL)
 			memcpy(P, environ, cnt * sizeof(char *));
 		lastenv = environ = P;
 		offset = cnt;
 		environ[cnt + 1] = NULL;
 	}
 	if (!(environ[offset] =			/* name + `=' + value */
-	    malloc((size_t)((int)(np - name) + l_value + 2))))
+	    malloc((int)(np - name) + l_value + 2)))
 		return (-1);
 	for (C = environ[offset]; (*C = *name++) && *C != '='; ++C)
 		;
diff --git a/libc/upstream-openbsd/lib/libc/string/strstr.c b/libc/upstream-openbsd/lib/libc/string/strstr.c
index 079d69d..241a080 100644
--- a/libc/upstream-openbsd/lib/libc/string/strstr.c
+++ b/libc/upstream-openbsd/lib/libc/string/strstr.c
@@ -1,7 +1,7 @@
-/*	$OpenBSD: strstr.c,v 1.8 2018/04/30 07:44:56 denis Exp $ */
+/*	$OpenBSD: strstr.c,v 1.9 2020/04/16 12:37:52 claudio Exp $ */
 
 /*
- * Copyright (c) 2005-2014 Rich Felker
+ * Copyright (c) 2005-2018 Rich Felker
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -24,13 +24,8 @@
  */
 
 #include <string.h>
-#include <stdlib.h>
 #include <stdint.h>
 
-#ifdef DEBUG
-#include <stdio.h>
-#endif
-
 static char *
 twobyte_strstr(const unsigned char *h, const unsigned char *n)
 {
@@ -146,11 +141,8 @@
 		/* Check last byte first; advance by shift on mismatch */
 		if (BITOP(byteset, h[l-1], &)) {
 			k = l-shift[h[l-1]];
-#ifdef DEBUG
-			printf("adv by %zu (on %c) at [%s] (%zu;l=%zu)\n", k, h[l-1], h, shift[h[l-1]], l);
-#endif
 			if (k) {
-				if (mem0 && mem && k < p) k = l-p;
+				if (k < mem) k = mem;
 				h += k;
 				mem = 0;
 				continue;
diff --git a/tests/Android.bp b/tests/Android.bp
index 598865b..7e6e742 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -72,6 +72,217 @@
 }
 
 // -----------------------------------------------------------------------------
+// Prebuilt shared libraries for use in tests.
+// -----------------------------------------------------------------------------
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-rw_load_segment",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-rw_load_segment.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-rw_load_segment.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-unaligned_shdr_offset",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-unaligned_shdr_offset.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shentsize",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shentsize.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shentsize.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shstrndx",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shstrndx.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shstrndx.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-empty_shdr_table",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-empty_shdr_table.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-empty_shdr_table.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-empty_shdr_table.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-empty_shdr_table.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shdr_table_offset",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_offset.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-zero_shdr_table_content",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-zero_shdr_table_content.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-zero_shdr_table_content.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-textrels",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-textrels.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-textrels.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-textrels.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-textrels.so"],
+        },
+    },
+}
+
+cc_prebuilt_test_library_shared {
+    name: "libtest_invalid-textrels2",
+    strip: {
+        none: true,
+    },
+    check_elf_files: false,
+    relative_install_path: "bionic-loader-test-libs/prebuilt-elf-files",
+    arch: {
+        arm: {
+            srcs: ["prebuilt-elf-files/arm/libtest_invalid-textrels2.so"],
+        },
+        arm64: {
+            srcs: ["prebuilt-elf-files/arm64/libtest_invalid-textrels2.so"],
+        },
+        x86: {
+            srcs: ["prebuilt-elf-files/x86/libtest_invalid-textrels2.so"],
+        },
+        x86_64: {
+            srcs: ["prebuilt-elf-files/x86_64/libtest_invalid-textrels2.so"],
+        },
+    },
+}
+
+// -----------------------------------------------------------------------------
 // All standard tests.
 // -----------------------------------------------------------------------------
 
@@ -736,15 +947,15 @@
         "libtest_with_dependency_loop",
         "libtest_with_dependency",
         "libtest_indirect_thread_local_dtor",
-        "libtest_invalid-empty_shdr_table.so",
-        "libtest_invalid-rw_load_segment.so",
-        "libtest_invalid-unaligned_shdr_offset.so",
-        "libtest_invalid-zero_shdr_table_content.so",
-        "libtest_invalid-zero_shdr_table_offset.so",
-        "libtest_invalid-zero_shentsize.so",
-        "libtest_invalid-zero_shstrndx.so",
-        "libtest_invalid-textrels.so",
-        "libtest_invalid-textrels2.so",
+        "libtest_invalid-empty_shdr_table",
+        "libtest_invalid-rw_load_segment",
+        "libtest_invalid-unaligned_shdr_offset",
+        "libtest_invalid-zero_shdr_table_content",
+        "libtest_invalid-zero_shdr_table_offset",
+        "libtest_invalid-zero_shentsize",
+        "libtest_invalid-zero_shstrndx",
+        "libtest_invalid-textrels",
+        "libtest_invalid-textrels2",
         "libtest_thread_local_dtor",
         "libtest_thread_local_dtor2",
         "preinit_getauxval_test_helper",
diff --git a/tests/Android.build.prebuilt.mk b/tests/Android.build.prebuilt.mk
deleted file mode 100644
index de8f5e6..0000000
--- a/tests/Android.build.prebuilt.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 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 $(CLEAR_VARS)
-LOCAL_MULTILIB := both
-LOCAL_MODULE := $(bionic_tests_module)
-LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/prebuilt-elf-files
-LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/bionic-loader-test-libs/prebuilt-elf-files
-LOCAL_MODULE_CLASS := EXECUTABLES
-
-LOCAL_SRC_FILES_arm := prebuilt-elf-files/arm/$(bionic_tests_module)
-LOCAL_SRC_FILES_arm64 := prebuilt-elf-files/arm64/$(bionic_tests_module)
-LOCAL_SRC_FILES_x86 := prebuilt-elf-files/x86/$(bionic_tests_module)
-LOCAL_SRC_FILES_x86_64 := prebuilt-elf-files/x86_64/$(bionic_tests_module)
-include $(BUILD_PREBUILT)
-bionic-loader-test-libs-target: $(LOCAL_MODULE)
-.PHONY: bionic-loader-test-libs-target
diff --git a/tests/Android.mk b/tests/Android.mk
index b5571e3..5ad4045 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -16,43 +16,6 @@
 
 LOCAL_PATH := $(call my-dir)
 
-# TODO(dimitry): replace with define once https://android-review.googlesource.com/247466 is reverted
-# https://github.com/google/kati/issues/83 is currently blocking it.
-
-# Move prebuilt test elf-files to $(TARGET_OUT_NATIVE_TESTS)
-bionic_tests_module := libtest_invalid-rw_load_segment.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-unaligned_shdr_offset.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shentsize.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shstrndx.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-empty_shdr_table.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shdr_table_offset.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-zero_shdr_table_content.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-textrels.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-bionic_tests_module := libtest_invalid-textrels2.so
-include $(LOCAL_PATH)/Android.build.prebuilt.mk
-
-ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
-build_host := true
-else
-build_host := false
-endif
-
 ifeq ($(HOST_OS)-$(HOST_ARCH),$(filter $(HOST_OS)-$(HOST_ARCH),linux-x86 linux-x86_64))
 
 # -----------------------------------------------------------------------------
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index d7b9bae..35e12eb 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -1623,9 +1623,7 @@
 #endif //  defined(__arm__)
 
 TEST(dlfcn, dlopen_invalid_rw_load_segment) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-rw_load_segment.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-rw_load_segment.so";
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
   std::string expected_dlerror = std::string("dlopen failed: \"") + libpath + "\": W+E load segments are not allowed";
@@ -1633,9 +1631,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_unaligned_shdr_offset) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-unaligned_shdr_offset.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-unaligned_shdr_offset.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1644,9 +1640,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shentsize) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shentsize.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shentsize.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1655,9 +1649,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shstrndx) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shstrndx.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shstrndx.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1666,9 +1658,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_empty_shdr_table) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-empty_shdr_table.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-empty_shdr_table.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1677,9 +1667,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shdr_table_offset) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shdr_table_offset.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_offset.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1688,9 +1676,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_zero_shdr_table_content) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-zero_shdr_table_content.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-zero_shdr_table_content.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1699,9 +1685,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_textrels) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-textrels.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
@@ -1710,9 +1694,7 @@
 }
 
 TEST(dlfcn, dlopen_invalid_textrels2) {
-  const std::string libpath = GetTestlibRoot() +
-                              "/" + kPrebuiltElfDir +
-                              "/libtest_invalid-textrels2.so";
+  const std::string libpath = GetPrebuiltElfDir() + "/libtest_invalid-textrels2.so";
 
   void* handle = dlopen(libpath.c_str(), RTLD_NOW);
   ASSERT_TRUE(handle == nullptr);
diff --git a/tests/gtest_globals.cpp b/tests/gtest_globals.cpp
index 4160237..5b5ede8 100644
--- a/tests/gtest_globals.cpp
+++ b/tests/gtest_globals.cpp
@@ -24,8 +24,9 @@
 #include <string>
 
 std::string GetTestlibRoot() {
-  // Calculate ANDROID_DATA assuming the binary is in "$ANDROID_DATA/somedir/binary-dir/binary"
-  std::string path = android::base::Dirname(android::base::GetExecutablePath()) + "/..";
+  // Typically the executable is /data/nativetest[64]/bionic-unit-tests/bionic-unit-tests, and the
+  // test libraries are in /data/nativetest[64]/bionic-loader-test-libs.
+  std::string path = android::base::GetExecutableDirectory() + "/..";
 
   std::string out_path;
   if (!android::base::Realpath(path.c_str(), &out_path)) {
diff --git a/tests/gtest_globals.h b/tests/gtest_globals.h
index b3c7b10..1bebb70 100644
--- a/tests/gtest_globals.h
+++ b/tests/gtest_globals.h
@@ -19,8 +19,10 @@
 
 #include <string>
 
-constexpr const char* kPrebuiltElfDir = "prebuilt-elf-files";
-
 std::string GetTestlibRoot();
 
+inline std::string GetPrebuiltElfDir() {
+  return GetTestlibRoot() + "/prebuilt-elf-files";
+}
+
 #endif  // _BIONIC_TESTS_GTEST_GLOBALS_H
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index 47a9033..55bd149 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -662,6 +662,46 @@
 #endif
 }
 
+#if defined(__BIONIC__)
+static void GetAllocatorVersion(bool* allocator_scudo) {
+  TemporaryFile tf;
+  ASSERT_TRUE(tf.fd != -1);
+  FILE* fp = fdopen(tf.fd, "w+");
+  tf.release();
+  ASSERT_TRUE(fp != nullptr);
+  ASSERT_EQ(0, malloc_info(0, fp));
+  ASSERT_EQ(0, fclose(fp));
+
+  std::string contents;
+  ASSERT_TRUE(android::base::ReadFileToString(tf.path, &contents));
+
+  tinyxml2::XMLDocument doc;
+  ASSERT_EQ(tinyxml2::XML_SUCCESS, doc.Parse(contents.c_str()));
+
+  auto root = doc.FirstChildElement();
+  ASSERT_NE(nullptr, root);
+  ASSERT_STREQ("malloc", root->Name());
+  std::string version(root->Attribute("version"));
+  *allocator_scudo = (version == "scudo-1");
+}
+#endif
+
+TEST(malloc, mallopt_scudo_only_options) {
+#if defined(__BIONIC__)
+  SKIP_WITH_HWASAN << "hwasan does not implement mallopt";
+  bool allocator_scudo;
+  GetAllocatorVersion(&allocator_scudo);
+  if (!allocator_scudo) {
+    GTEST_SKIP() << "scudo allocator only test";
+  }
+  ASSERT_EQ(1, mallopt(M_CACHE_COUNT_MAX, 100));
+  ASSERT_EQ(1, mallopt(M_CACHE_SIZE_MAX, 1024 * 1024 * 2));
+  ASSERT_EQ(1, mallopt(M_TSDS_COUNT_MAX, 8));
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}
+
 TEST(malloc, reallocarray_overflow) {
 #if HAVE_REALLOCARRAY
   // Values that cause overflow to a result small enough (8 on LP64) that malloc would "succeed".
diff --git a/tests/time_test.cpp b/tests/time_test.cpp
index 74d691d..5a977c2 100644
--- a/tests/time_test.cpp
+++ b/tests/time_test.cpp
@@ -142,7 +142,7 @@
   t.tm_mday = 10;
 
 #if !defined(__LP64__)
-  // 32-bit bionic stupidly had a signed 32-bit time_t.
+  // 32-bit bionic has a signed 32-bit time_t.
   ASSERT_EQ(-1, mktime(&t));
   ASSERT_EQ(EOVERFLOW, errno);
 #else
diff --git a/tools/versioner/src/Utils.cpp b/tools/versioner/src/Utils.cpp
index ca186a4..dc6b5dd 100644
--- a/tools/versioner/src/Utils.cpp
+++ b/tools/versioner/src/Utils.cpp
@@ -64,7 +64,7 @@
 
     if (ent->fts_info & FTS_D) {
       if (ignored_directories.count(ent->fts_path) != 0) {
-        // fts_read guarantees that `ent` is valid and sane to hold on to until
+        // fts_read guarantees that `ent` is valid and okay to hold on to until
         // after it's returned with FTS_DP set.
         skipping = ent;
       }