Merge changes from topics "Ic7ea0f075751f8f077612617802775d2d0a799dc", "Iec02ae89f4a3d2ffe298817240f404e54b109a52"
* changes:
Add a bionic-benchmarks-static target.
Make our definition of std::nothrow weak.
diff --git a/TEST_MAPPING b/TEST_MAPPING
index ae61304..11efdae 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -17,6 +17,9 @@
},
{
"name": "memunreachable_unit_test"
+ },
+ {
+ "name": "CtsTaggingHostTestCases"
}
]
}
diff --git a/apex/Android.bp b/apex/Android.bp
index 5bf078a..c97eb15 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -26,6 +26,9 @@
"libc_malloc_debug",
"libc_malloc_hooks",
],
+ binaries: [
+ "linkerconfig",
+ ],
multilib: {
both: {
binaries: [
diff --git a/libc/Android.bp b/libc/Android.bp
index 4d63751..447d17b 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -506,8 +506,6 @@
"upstream-openbsd/lib/libc/stdio/open_wmemstream.c",
"upstream-openbsd/lib/libc/stdio/rget.c",
"upstream-openbsd/lib/libc/stdio/setvbuf.c",
- "upstream-openbsd/lib/libc/stdio/tempnam.c",
- "upstream-openbsd/lib/libc/stdio/tmpnam.c",
"upstream-openbsd/lib/libc/stdio/ungetc.c",
"upstream-openbsd/lib/libc/stdio/ungetwc.c",
"upstream-openbsd/lib/libc/stdio/vasprintf.c",
diff --git a/libc/NOTICE b/libc/NOTICE
index 58d6679..f7d73d8 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -2368,38 +2368,6 @@
-------------------------------------------------------------------
-Copyright (c) 1990, 1993, 1994
- The Regents of the University of California. All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-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.
-
--------------------------------------------------------------------
-
Copyright (c) 1991 The Regents of the University of California.
All rights reserved.
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index 7601ddd..2c5d4d8 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -30,16 +30,14 @@
#include "malloc_common.h"
#include "malloc_tagged_pointers.h"
+#include <bionic/pthread_internal.h>
#include <platform/bionic/malloc.h>
#include <platform/bionic/mte_kernel.h>
-#include <bionic/pthread_internal.h>
-
-#include "private/ScopedPthreadMutexLocker.h"
-
extern "C" void scudo_malloc_disable_memory_tagging();
extern "C" void scudo_malloc_set_track_allocation_stacks(int);
+// Protected by `g_heap_tagging_lock`.
static HeapTaggingLevel heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
void SetDefaultHeapTaggingLevel() {
@@ -94,10 +92,15 @@
}
#endif
-bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
- static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
- ScopedPthreadMutexLocker locker(&mutex);
+pthread_mutex_t g_heap_tagging_lock = PTHREAD_MUTEX_INITIALIZER;
+// Requires `g_heap_tagging_lock` to be held.
+HeapTaggingLevel GetHeapTaggingLevel() {
+ return heap_tagging_level;
+}
+
+// Requires `g_heap_tagging_lock` to be held.
+bool SetHeapTaggingLevel(void* arg, size_t arg_size) {
if (arg_size != sizeof(HeapTaggingLevel)) {
return false;
}
diff --git a/libc/bionic/heap_tagging.h b/libc/bionic/heap_tagging.h
index 2aaf608..db45fc1 100644
--- a/libc/bionic/heap_tagging.h
+++ b/libc/bionic/heap_tagging.h
@@ -28,7 +28,19 @@
#pragma once
+#include <bionic/pthread_internal.h>
+#include <platform/bionic/malloc.h>
#include <stddef.h>
+// Expected to be called in a single-threaded context during libc init, so no
+// synchronization required.
void SetDefaultHeapTaggingLevel();
+
+// Lock for the heap tagging level. You may find ScopedPthreadMutexLocker
+// useful for RAII on this lock.
+extern pthread_mutex_t g_heap_tagging_lock;
+
+// These functions can be called in a multithreaded context, and thus should
+// only be called when holding the `g_heap_tagging_lock`.
bool SetHeapTaggingLevel(void* arg, size_t arg_size);
+HeapTaggingLevel GetHeapTaggingLevel();
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index 0c80f4e..1536333 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -306,9 +306,12 @@
// Open the netlink socket and ask for all the links and addresses.
NetlinkConnection nc;
- // SELinux policy only allows RTM_GETLINK messages to be sent by system apps.
+ // SELinux policy only allows RTM_GETLINK messages to be sent by:
+ // - System apps
+ // - Apps with a target SDK version lower than R
bool getlink_success = false;
- if (getuid() < FIRST_APPLICATION_UID) {
+ if (getuid() < FIRST_APPLICATION_UID ||
+ android_get_application_target_sdk_version() < __ANDROID_API_R__) {
getlink_success = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out);
}
bool getaddr_success =
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 6b7006d..0ee12a7 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -38,8 +38,9 @@
#include <stdint.h>
#include <stdio.h>
-#include <private/bionic_config.h>
#include <platform/bionic/malloc.h>
+#include <private/ScopedPthreadMutexLocker.h>
+#include <private/bionic_config.h>
#include "gwp_asan_wrappers.h"
#include "heap_tagging.h"
@@ -316,6 +317,7 @@
return LimitEnable(arg, arg_size);
}
if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
+ ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
return SetHeapTaggingLevel(arg, arg_size);
}
if (opcode == M_INITIALIZE_GWP_ASAN) {
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index eeeaff9..2d6a1bb 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -58,6 +58,7 @@
#include <android/dlext.h>
#include <platform/bionic/malloc.h>
+#include <private/ScopedPthreadMutexLocker.h>
#include <private/bionic_config.h>
#include <private/bionic_defs.h>
#include <private/bionic_malloc_dispatch.h>
@@ -523,6 +524,7 @@
return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
}
if (opcode == M_SET_HEAP_TAGGING_LEVEL) {
+ ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
return SetHeapTaggingLevel(arg, arg_size);
}
if (opcode == M_INITIALIZE_GWP_ASAN) {
diff --git a/libc/bionic/memory_mitigation_state.cpp b/libc/bionic/memory_mitigation_state.cpp
index abb1e8d..4761d88 100644
--- a/libc/bionic/memory_mitigation_state.cpp
+++ b/libc/bionic/memory_mitigation_state.cpp
@@ -39,8 +39,10 @@
#include <bionic/malloc.h>
#include <bionic/mte.h>
+#include <private/ScopedPthreadMutexLocker.h>
+#include <private/ScopedRWLock.h>
+
#include "heap_tagging.h"
-#include "private/ScopedRWLock.h"
#include "pthread_internal.h"
extern "C" void scudo_malloc_set_zero_contents(int zero_contents);
@@ -54,8 +56,13 @@
scudo_malloc_set_zero_contents(0);
#endif
- HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_NONE;
- SetHeapTaggingLevel(reinterpret_cast<void*>(&level), sizeof(level));
+ ScopedPthreadMutexLocker locker(&g_heap_tagging_lock);
+
+ HeapTaggingLevel current_level = GetHeapTaggingLevel();
+ if (current_level != M_HEAP_TAGGING_LEVEL_NONE && current_level != M_HEAP_TAGGING_LEVEL_TBI) {
+ HeapTaggingLevel level = M_HEAP_TAGGING_LEVEL_NONE;
+ SetHeapTaggingLevel(reinterpret_cast<void*>(&level), sizeof(level));
+ }
return true;
}
diff --git a/libc/bionic/tmpfile.cpp b/libc/bionic/tmpfile.cpp
index d7ce897..3d04610 100644
--- a/libc/bionic/tmpfile.cpp
+++ b/libc/bionic/tmpfile.cpp
@@ -35,6 +35,7 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -99,3 +100,48 @@
return fp;
}
__strong_alias(tmpfile64, tmpfile);
+
+char* tempnam(const char* dir, const char* prefix) {
+ // This function is a terrible idea, marked deprecated in our headers,
+ // and marked obsolescent by POSIX.1-2008, but we make some effort anyway
+ // since we can't easily remove it...
+
+ // $TMPDIR overrides any directory passed in.
+ char* tmpdir = getenv("TMPDIR");
+ if (tmpdir != nullptr) dir = tmpdir;
+
+ // If we still have no directory, we'll give you a default.
+ // It's useless for apps, but good enough for the shell.
+ if (dir == nullptr) dir = "/data/local/tmp";
+
+ // Default prefix?
+ if (prefix == nullptr) prefix = "tempnam.";
+
+ // Make up a mktemp(3) template and defer to it for the real work.
+ char* path = nullptr;
+ if (asprintf(&path, "%s/%sXXXXXXXXXX", dir, prefix) == -1) return nullptr;
+ if (mktemp(path) == nullptr) {
+ free(path);
+ return nullptr;
+ }
+ return path;
+}
+
+char* tmpnam(char* s) {
+ // This function is a terrible idea, marked deprecated in our headers,
+ // and marked obsolescent by POSIX-1.2008, but we make some effort anyway
+ // since we can't easily remove it...
+
+ // Default buffer?
+ static char buf[L_tmpnam];
+ if (s == nullptr) s = buf;
+
+ // Use $TMPDIR if set, or fall back to /data/local/tmp otherwise.
+ // Useless for apps, but good enough for the shell.
+ const char* dir = getenv("TMPDIR");
+ if (dir == nullptr) dir = "/data/local/tmp";
+
+ // Make up a mktemp(3) template and defer to it for the real work.
+ snprintf(s, L_tmpnam, "%s/tmpnam.XXXXXXXXXX", dir);
+ return mktemp(s);
+}
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index 1bf578c..9de12a4 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -160,7 +160,7 @@
int vsprintf(char* __s, const char* __fmt, va_list __args)
__printflike(2, 0) __warnattr_strict("vsprintf is often misused; please use vsnprintf");
char* tmpnam(char* __s)
- __warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
+ __warnattr("tmpnam is unsafe, use mkstemp or tmpfile instead");
#define P_tmpdir "/tmp/" /* deprecated */
char* tempnam(const char* __dir, const char* __prefix)
__warnattr("tempnam is unsafe, use mkstemp or tmpfile instead");
diff --git a/libc/kernel/tools/generate_uapi_headers.sh b/libc/kernel/tools/generate_uapi_headers.sh
index 4e7d2af..7e49cde 100755
--- a/libc/kernel/tools/generate_uapi_headers.sh
+++ b/libc/kernel/tools/generate_uapi_headers.sh
@@ -218,12 +218,11 @@
fi
if [[ ${SKIP_GENERATION} -eq 0 ]]; then
- # Clean up any leftover headers.
- make distclean
-
# Build all of the generated headers.
for arch in "${ARCH_LIST[@]}"; do
echo "Generating headers for arch ${arch}"
+ # Clean up any leftover headers.
+ make ARCH=${arch} distclean
make ARCH=${arch} headers_install
done
fi
@@ -269,3 +268,12 @@
"${ANDROID_KERNEL_DIR}/scsi" \
"${KERNEL_DIR}"
echo "Headers updated."
+
+if [[ ${SKIP_GENERATION} -eq 0 ]]; then
+ cd "${KERNEL_DIR}"
+ # Clean all of the generated headers.
+ for arch in "${ARCH_LIST[@]}"; do
+ echo "Cleaning kernel files for arch ${arch}"
+ make ARCH=${arch} distclean
+ done
+fi
diff --git a/libc/upstream-openbsd/lib/libc/stdio/tempnam.c b/libc/upstream-openbsd/lib/libc/stdio/tempnam.c
deleted file mode 100644
index d2c848c..0000000
--- a/libc/upstream-openbsd/lib/libc/stdio/tempnam.c
+++ /dev/null
@@ -1,100 +0,0 @@
-/* $OpenBSD: tempnam.c,v 1.20 2017/11/28 06:55:49 tb Exp $ */
-/*
- * Copyright (c) 1988, 1993
- * The 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.
- */
-
-#include <errno.h>
-#include <limits.h>
-#include <paths.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-__warn_references(tempnam,
- "tempnam() possibly used unsafely; consider using mkstemp()");
-
-char *
-tempnam(const char *dir, const char *pfx)
-{
- int sverrno, len;
- char *f, *name;
-
- if (!(name = malloc(PATH_MAX)))
- return(NULL);
-
- if (!pfx)
- pfx = "tmp.";
-
- if (issetugid() == 0 && (f = getenv("TMPDIR")) && *f != '\0') {
- len = snprintf(name, PATH_MAX, "%s%s%sXXXXXXXXXX", f,
- f[strlen(f) - 1] == '/' ? "" : "/", pfx);
- if (len < 0 || len >= PATH_MAX) {
- errno = ENAMETOOLONG;
- goto fail;
- }
- if ((f = _mktemp(name)))
- return(f);
- }
-
- if (dir != NULL) {
- f = *dir ? (char *)dir : ".";
- len = snprintf(name, PATH_MAX, "%s%s%sXXXXXXXXXX", f,
- f[strlen(f) - 1] == '/' ? "" : "/", pfx);
- if (len < 0 || len >= PATH_MAX) {
- errno = ENAMETOOLONG;
- goto fail;
- }
- if ((f = _mktemp(name)))
- return(f);
- }
-
- f = P_tmpdir;
- len = snprintf(name, PATH_MAX, "%s%sXXXXXXXXX", f, pfx);
- if (len < 0 || len >= PATH_MAX) {
- errno = ENAMETOOLONG;
- goto fail;
- }
- if ((f = _mktemp(name)))
- return(f);
-
- f = _PATH_TMP;
- len = snprintf(name, PATH_MAX, "%s%sXXXXXXXXX", f, pfx);
- if (len < 0 || len >= PATH_MAX) {
- errno = ENAMETOOLONG;
- goto fail;
- }
- if ((f = _mktemp(name)))
- return(f);
-
-fail:
- sverrno = errno;
- free(name);
- errno = sverrno;
- return(NULL);
-}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c b/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
deleted file mode 100644
index 52cd43d..0000000
--- a/libc/upstream-openbsd/lib/libc/stdio/tmpnam.c
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $OpenBSD: tmpnam.c,v 1.12 2017/11/28 06:55:49 tb Exp $ */
-/*-
- * Copyright (c) 1990, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * 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.
- */
-
-#include <sys/types.h>
-
-#include <stdio.h>
-#include <unistd.h>
-
-__warn_references(tmpnam,
- "tmpnam() possibly used unsafely; consider using mkstemp()");
-
-char *
-tmpnam(char *s)
-{
- static u_long tmpcount;
- static char buf[L_tmpnam];
-
- if (s == NULL)
- s = buf;
- (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXXXXX", P_tmpdir, tmpcount);
- ++tmpcount;
- return (_mktemp(s));
-}
diff --git a/tests/Android.bp b/tests/Android.bp
index a7f6229..477c8fc 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -332,6 +332,7 @@
"fenv_test.cpp",
"_FILE_OFFSET_BITS_test.cpp",
"float_test.cpp",
+ "fnmatch_test.cpp",
"ftw_test.cpp",
"getauxval_test.cpp",
"getcwd_test.cpp",
diff --git a/tests/fnmatch_test.cpp b/tests/fnmatch_test.cpp
new file mode 100644
index 0000000..d28aefa
--- /dev/null
+++ b/tests/fnmatch_test.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * 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
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ *
+ * 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 ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include <fnmatch.h>
+
+TEST(fnmatch, basic) {
+ EXPECT_EQ(0, fnmatch("abc", "abc", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("abc", "abd", 0));
+}
+
+TEST(fnmatch, casefold) {
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("abc", "aBc", 0));
+ EXPECT_EQ(0, fnmatch("abc", "aBc", FNM_CASEFOLD));
+}
+
+TEST(fnmatch, character_class) {
+ // Literal.
+ EXPECT_EQ(0, fnmatch("ab[cd]", "abc", 0));
+ EXPECT_EQ(0, fnmatch("ab[cd]", "abd", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab[cd]", "abe", 0));
+
+ // Inverted literal.
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab[^cd]", "abc", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab[^cd]", "abd", 0));
+ EXPECT_EQ(0, fnmatch("ab[^cd]", "abe", 0));
+
+ // Range.
+ EXPECT_EQ(0, fnmatch("a[0-9]b", "a0b", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("a[0-9]b", "aOb", 0));
+
+ // Inverted range.
+ EXPECT_EQ(0, fnmatch("a[^0-9]b", "aOb", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("a[^0-9]b", "a0b", 0));
+
+ // Named.
+ EXPECT_EQ(0, fnmatch("a[[:digit:]]b", "a0b", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("a[[:digit:]]b", "aOb", 0));
+
+ // Inverted named.
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("a[^[:digit:]]b", "a0b", 0));
+ EXPECT_EQ(0, fnmatch("a[^[:digit:]]b", "aOb", 0));
+}
+
+TEST(fnmatch, wild_any) {
+ EXPECT_EQ(0, fnmatch("ab*", "ab", 0));
+ EXPECT_EQ(0, fnmatch("ab*", "abc", 0));
+ EXPECT_EQ(0, fnmatch("ab*", "abcd", 0));
+ EXPECT_EQ(0, fnmatch("ab*", "ab/cd", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab*", "ab/cd", FNM_PATHNAME));
+}
+
+TEST(fnmatch, wild_one) {
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab?", "ab", 0));
+ EXPECT_EQ(0, fnmatch("ab?", "abc", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab?", "abcd", 0));
+ EXPECT_EQ(0, fnmatch("ab?d", "abcd", 0));
+ EXPECT_EQ(0, fnmatch("ab?cd", "ab/cd", 0));
+ EXPECT_EQ(FNM_NOMATCH, fnmatch("ab?cd", "ab/cd", FNM_PATHNAME));
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index c21c3b8..5680f95 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -33,6 +33,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/test_utils.h>
#include <android-base/unique_fd.h>
#include "BionicDeathTest.h"
@@ -2816,3 +2817,69 @@
ASSERT_TRUE(fp == nullptr);
ASSERT_EQ(ENOENT, errno);
}
+
+static void tempnam_test(bool has_TMPDIR, const char* dir, const char* prefix, const char* re) {
+ if (has_TMPDIR) {
+ setenv("TMPDIR", "/my/tmp/dir", 1);
+ } else {
+ unsetenv("TMPDIR");
+ }
+ char* s1 = tempnam(dir, prefix);
+ char* s2 = tempnam(dir, prefix);
+ ASSERT_MATCH(s1, re);
+ ASSERT_MATCH(s2, re);
+ ASSERT_STRNE(s1, s2);
+ free(s1);
+ free(s2);
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_with_TMPDIR) {
+ tempnam_test(true, nullptr, nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_system_prefix_without_TMPDIR) {
+ tempnam_test(false, nullptr, nullptr, "^/data/local/tmp/.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_with_TMPDIR) {
+ tempnam_test(true, nullptr, "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__system_directory_user_prefix_without_TMPDIR) {
+ tempnam_test(false, nullptr, "prefix", "^/data/local/tmp/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_with_TMPDIR) {
+ tempnam_test(true, "/a/b/c", nullptr, "^/my/tmp/dir/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_system_prefix_without_TMPDIR) {
+ tempnam_test(false, "/a/b/c", nullptr, "^/a/b/c/.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_with_TMPDIR) {
+ tempnam_test(true, "/a/b/c", "prefix", "^/my/tmp/dir/prefix.*");
+}
+
+TEST(STDIO_TEST, tempnam__user_directory_user_prefix_without_TMPDIR) {
+ tempnam_test(false, "/a/b/c", "prefix", "^/a/b/c/prefix.*");
+}
+
+static void tmpnam_test(char* s) {
+ char s1[L_tmpnam], s2[L_tmpnam];
+
+ strcpy(s1, tmpnam(s));
+ strcpy(s2, tmpnam(s));
+ ASSERT_MATCH(s1, "/tmp/.*");
+ ASSERT_MATCH(s2, "/tmp/.*");
+ ASSERT_STRNE(s1, s2);
+}
+
+TEST(STDIO_TEST, tmpnam) {
+ tmpnam_test(nullptr);
+}
+
+TEST(STDIO_TEST, tmpnam_buf) {
+ char buf[L_tmpnam];
+ tmpnam_test(buf);
+}