diff options
author | Elliott Hughes <enh@google.com> | 2020-12-04 18:51:42 -0800 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2020-12-08 22:26:06 -0800 |
commit | 439ebbd3492ad3a8b8398fa80b0860baeb50a40e (patch) | |
tree | 5bcaa629808b35484cefbcda47d91c1dcbc21171 | |
parent | 925431a072737d4c1bbf18f3da7ab24a25486870 (diff) | |
download | bionic-439ebbd3492ad3a8b8398fa80b0860baeb50a40e.tar.gz |
Simplify and improve tempnam() and tmpnam().
They're both obsolescent in POSIX.1-2008, and you really shouldn't be
using them, but since we can't actually delete them...
This change makes them both obey $TMPDIR if set, and fall back to
/data/local/tmp otherwise. That's as good as we've managed for anything
else such as tmpfile(3).
Also add some tests.
Bug: http://b/174682340
Test: treehugger
Change-Id: Ieef99dcc2062f84b2b7cbae046787fdfe975e772
-rw-r--r-- | libc/Android.bp | 2 | ||||
-rw-r--r-- | libc/NOTICE | 32 | ||||
-rw-r--r-- | libc/bionic/tmpfile.cpp | 46 | ||||
-rw-r--r-- | libc/include/stdio.h | 2 | ||||
-rw-r--r-- | libc/upstream-openbsd/lib/libc/stdio/tempnam.c | 100 | ||||
-rw-r--r-- | libc/upstream-openbsd/lib/libc/stdio/tmpnam.c | 53 | ||||
-rw-r--r-- | tests/stdio_test.cpp | 67 |
7 files changed, 114 insertions, 188 deletions
diff --git a/libc/Android.bp b/libc/Android.bp index 4d63751f6..447d17b75 100644 --- a/libc/Android.bp +++ b/libc/Android.bp @@ -506,8 +506,6 @@ cc_library_static { "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 58d66795f..f7d73d8f8 100644 --- a/libc/NOTICE +++ b/libc/NOTICE @@ -2368,38 +2368,6 @@ SUCH DAMAGE. ------------------------------------------------------------------- -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/tmpfile.cpp b/libc/bionic/tmpfile.cpp index d7ce897e1..3d04610a4 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 @@ FILE* tmpfile() { 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 1bf578c1d..9de12a47f 100644 --- a/libc/include/stdio.h +++ b/libc/include/stdio.h @@ -160,7 +160,7 @@ int sprintf(char* __s, const char* __fmt, ...) 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/upstream-openbsd/lib/libc/stdio/tempnam.c b/libc/upstream-openbsd/lib/libc/stdio/tempnam.c deleted file mode 100644 index d2c848c8f..000000000 --- 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 52cd43d94..000000000 --- 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/stdio_test.cpp b/tests/stdio_test.cpp index c21c3b8b6..5680f9556 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 @@ TEST(STDIO_TEST, fopen_ENOENT) { 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); +} |