Those obnoxious "mktemp is not safe" warnings

Zack Weinberg zackw@Stanford.EDU
Tue Mar 20 21:25:00 GMT 2001


On Mon, Mar 19, 2001 at 08:23:53PM -0500, DJ Delorie wrote:
> 
> Too many changes at once.  I see at least three:
> 
> * split out choose_temp_base
> * change search logic
> * fix __inline__

Fair enough.  This version just splits choose_temp_base into its own
file (well, actually it leaves choose_temp_base where it is and splits
everything else into its own file.)

zw

	* choose-temp.c: Split off make_temp_file, and the code
	duplicated between it and choose_temp_base, into...
	* make-temp-file.c: ... here; new file.

	* Makefile.in (CFILES): Add make-temp-file.c.
	(REQUIRED_OFILES): Add make-temp-file.o.

===================================================================
Index: libiberty/Makefile.in
--- libiberty/Makefile.in	2001/03/10 10:41:24	1.59
+++ libiberty/Makefile.in	2001/03/21 05:23:28
@@ -125,7 +125,7 @@ CFILES = asprintf.c alloca.c argv.c atex
         cp-demangle.c dyn-string.c fdmatch.c fnmatch.c getcwd.c		      \
 	getpwd.c getopt.c getopt1.c getpagesize.c getruntime.c		      \
 	floatformat.c hashtab.c hex.c index.c insque.c lbasename.c            \
-	md5.c memchr.c							      \
+	md5.c make-temp-file.c memchr.c					      \
 	memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c  \
 	partition.c pexecute.c putenv.c random.c rename.c rindex.c setenv.c   \
 	sigsetmask.c safe-ctype.c sort.c spaces.c splay-tree.c strcasecmp.c   \
@@ -138,7 +138,7 @@ CFILES = asprintf.c alloca.c argv.c atex
 REQUIRED_OFILES = argv.o alloca.o choose-temp.o concat.o cplus-dem.o          \
 	cp-demangle.o dyn-string.o fdmatch.o fnmatch.o getopt.o getopt1.o     \
 	getpwd.o getruntime.o hashtab.o hex.o floatformat.o lbasename.o       \
-        md5.o objalloc.o						      \
+        md5.o make-temp-file.o objalloc.o				      \
 	obstack.o partition.o pexecute.o safe-ctype.o sort.o spaces.o         \
 	splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o       \
 	xmemdup.o xstrdup.o xstrerror.o
===================================================================
Index: libiberty/choose-temp.c
--- libiberty/choose-temp.c	2000/06/07 21:13:14	1.15
+++ libiberty/choose-temp.c	2001/03/21 05:23:28
@@ -17,81 +17,25 @@ License along with libiberty; see the fi
 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-/* This file exports two functions: choose_temp_base and make_temp_file.  */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 #include <stdio.h>	/* May get P_tmpdir.  */
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
-#ifdef HAVE_SYS_FILE_H
-#include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
-#endif
-
-#ifndef R_OK
-#define R_OK 4
-#define W_OK 2
-#define X_OK 1
-#endif
 
 #include "libiberty.h"
-extern int mkstemps ();
-
-#ifndef IN_GCC
-#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN__) && ! defined (_UWIN))
-#define DIR_SEPARATOR '\\'
-#endif
-#endif
+extern char *choose_tmpdir PARAMS ((void));
 
-#ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
-#endif
-
-/* On MSDOS, write temp files in current dir
-   because there's no place else we can expect to use.  */
-/* ??? Although the current directory is tried as a last resort,
-   this is left in so that on MSDOS it is preferred to /tmp on the
-   off chance that someone requires this, since that was the previous
-   behaviour.  */
-#ifdef __MSDOS__
-#ifndef P_tmpdir
-#define P_tmpdir "."
-#endif
-#endif
-
 /* Name of temporary file.
    mktemp requires 6 trailing X's.  */
 #define TEMP_FILE "ccXXXXXX"
-
-/* Subroutine of choose_temp_base.
-   If BASE is non-NULL, return it.
-   Otherwise it checks if DIR is a usable directory.
-   If success, DIR is returned.
-   Otherwise NULL is returned.  */
-
-static const char *try PARAMS ((const char *, const char *));
-
-static const char *
-try (dir, base)
-     const char *dir, *base;
-{
-  if (base != 0)
-    return base;
-  if (dir != 0
-      && access (dir, R_OK | W_OK | X_OK) == 0)
-    return dir;
-  return 0;
-}
+#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
 
 /* Return a prefix for temporary file names or NULL if unable to find one.
    The current directory is chosen if all else fails so the program is
@@ -104,102 +48,17 @@ try (dir, base)
 char *
 choose_temp_base ()
 {
-  const char *base = 0;
+  const char *base = choose_tmpdir ();
   char *temp_filename;
   int len;
-  static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
-  static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
 
-  base = try (getenv ("TMPDIR"), base);
-  base = try (getenv ("TMP"), base);
-  base = try (getenv ("TEMP"), base);
-
-#ifdef P_tmpdir
-  base = try (P_tmpdir, base);
-#endif
-
-  /* Try /usr/tmp, then /tmp.  */
-  base = try (usrtmp, base);
-  base = try (tmp, base);
- 
-  /* If all else fails, use the current directory!  */
-  if (base == 0)
-    base = ".";
-
   len = strlen (base);
-  temp_filename = xmalloc (len + 1 /*DIR_SEPARATOR*/
-			   + strlen (TEMP_FILE) + 1);
+  temp_filename = xmalloc (len + TEMP_FILE_LEN + 1);
   strcpy (temp_filename, base);
-
-  if (len != 0
-      && temp_filename[len-1] != '/'
-      && temp_filename[len-1] != DIR_SEPARATOR)
-    temp_filename[len++] = DIR_SEPARATOR;
   strcpy (temp_filename + len, TEMP_FILE);
 
   mktemp (temp_filename);
   if (strlen (temp_filename) == 0)
-    abort ();
-  return temp_filename;
-}
-/* Return a temporary file name (as a string) or NULL if unable to create
-   one.  */
-
-char *
-make_temp_file (suffix)
-     const char *suffix;
-{
-  const char *base = 0;
-  char *temp_filename;
-  int base_len, suffix_len;
-  int fd;
-  static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
-  static char usrtmp[] = { DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
-
-  base = try (getenv ("TMPDIR"), base);
-  base = try (getenv ("TMP"), base);
-  base = try (getenv ("TEMP"), base);
-
-#ifdef P_tmpdir
-  base = try (P_tmpdir, base);
-#endif
-
-  /* Try /usr/tmp, then /tmp.  */
-  base = try (usrtmp, base);
-  base = try (tmp, base);
- 
-  /* If all else fails, use the current directory!  */
-  if (base == 0)
-    base = ".";
-
-  base_len = strlen (base);
-
-  if (suffix)
-    suffix_len = strlen (suffix);
-  else
-    suffix_len = 0;
-
-  temp_filename = xmalloc (base_len + 1 /*DIR_SEPARATOR*/
-			   + strlen (TEMP_FILE)
-			   + suffix_len + 1);
-  strcpy (temp_filename, base);
-
-  if (base_len != 0
-      && temp_filename[base_len-1] != '/'
-      && temp_filename[base_len-1] != DIR_SEPARATOR)
-    temp_filename[base_len++] = DIR_SEPARATOR;
-  strcpy (temp_filename + base_len, TEMP_FILE);
-
-  if (suffix)
-    strcat (temp_filename, suffix);
-
-  fd = mkstemps (temp_filename, suffix_len);
-  /* If mkstemps failed, then something bad is happening.  Maybe we should
-     issue a message about a possible security attack in progress?  */
-  if (fd == -1)
-    abort ();
-  /* Similarly if we can not close the file.  */
-  if (close (fd))
     abort ();
   return temp_filename;
 }
===================================================================
Index: libiberty/make-temp-file.c
--- libiberty/make-temp-file.c	Tue May  5 13:32:27 1998
+++ libiberty/make-temp-file.c	Tue Mar 20 21:23:28 2001
@@ -0,0 +1,174 @@
+/* Utility to pick a temporary filename prefix.
+   Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB.  If not,
+write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>	/* May get P_tmpdir.  */
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
+#endif
+
+#ifndef R_OK
+#define R_OK 4
+#define W_OK 2
+#define X_OK 1
+#endif
+
+#include "libiberty.h"
+extern int mkstemps PARAMS ((char *, int));
+
+#ifndef IN_GCC
+#if defined (__MSDOS__) || (defined (_WIN32) && ! defined (__CYGWIN__) && ! defined (_UWIN))
+#define DIR_SEPARATOR '\\'
+#endif
+#endif
+
+#ifndef DIR_SEPARATOR
+#define DIR_SEPARATOR '/'
+#endif
+
+/* On MSDOS, write temp files in current dir
+   because there's no place else we can expect to use.  */
+/* ??? Although the current directory is tried as a last resort,
+   this is left in so that on MSDOS it is preferred to /tmp on the
+   off chance that someone requires this, since that was the previous
+   behaviour.  */
+#ifdef __MSDOS__
+#ifndef P_tmpdir
+#define P_tmpdir "."
+#endif
+#endif
+
+/* Name of temporary file.
+   mktemp requires 6 trailing X's.  */
+#define TEMP_FILE "ccXXXXXX"
+#define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
+
+/* Subroutine of choose_tmpdir.
+   If BASE is non-NULL, return it.
+   Otherwise it checks if DIR is a usable directory.
+   If success, DIR is returned.
+   Otherwise NULL is returned.  */
+
+static const char *try PARAMS ((const char *, const char *));
+
+static const char *
+try (dir, base)
+     const char *dir, *base;
+{
+  if (base != 0)
+    return base;
+  if (dir != 0
+      && access (dir, R_OK | W_OK | X_OK) == 0)
+    return dir;
+  return 0;
+}
+
+static char tmp[] = { DIR_SEPARATOR, 't', 'm', 'p', 0 };
+static char usrtmp[] =
+{ DIR_SEPARATOR, 'u', 's', 'r', DIR_SEPARATOR, 't', 'm', 'p', 0 };
+
+static char *memoized_tmpdir;
+
+char *
+choose_tmpdir ()
+{
+  const char *base = 0;
+  char *tmpdir;
+  unsigned int len;
+
+  if (memoized_tmpdir)
+    return memoized_tmpdir;
+
+  base = try (getenv ("TMPDIR"), base);
+  base = try (getenv ("TMP"), base);
+  base = try (getenv ("TEMP"), base);
+
+#ifdef P_tmpdir
+  base = try (P_tmpdir, base);
+#endif
+
+  /* Try /usr/tmp, then /tmp.  */
+  base = try (usrtmp, base);
+  base = try (tmp, base);
+ 
+  /* If all else fails, use the current directory!  */
+  if (base == 0)
+    base = ".";
+
+  /* Append DIR_SEPARATOR to the directory we've chosen
+     and return it.  */
+  len = strlen (base);
+  tmpdir = xmalloc (len + 2);
+  strcpy (tmpdir, base);
+  tmpdir[len] = DIR_SEPARATOR;
+  tmpdir[len+1] = '\0';
+
+  memoized_tmpdir = tmpdir;
+  return tmpdir;
+}
+
+/* Return a temporary file name (as a string) or NULL if unable to create
+   one.  SUFFIX is a suffix to append to the file name.  The string is
+   malloced, and the temporary file has been created.  */
+
+char *
+make_temp_file (suffix)
+     const char *suffix;
+{
+  const char *base = choose_tmpdir ();
+  char *temp_filename;
+  int base_len, suffix_len;
+  int fd;
+
+  if (suffix == 0)
+    suffix = "";
+
+  base_len = strlen (base);
+  suffix_len = strlen (suffix);
+
+  temp_filename = xmalloc (base_len
+			   + TEMP_FILE_LEN
+			   + suffix_len + 1);
+  strcpy (temp_filename, base);
+  strcpy (temp_filename + base_len, TEMP_FILE);
+  strcpy (temp_filename + base_len + TEMP_FILE_LEN, suffix);
+
+  fd = mkstemps (temp_filename, suffix_len);
+  /* If mkstemps failed, then something bad is happening.  Maybe we should
+     issue a message about a possible security attack in progress?  */
+  if (fd == -1)
+    abort ();
+  /* Similarly if we can not close the file.  */
+  if (close (fd))
+    abort ();
+  return temp_filename;
+}



More information about the Gcc-patches mailing list