bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

stdio-safer and tmpfile


From: Eric Blake
Subject: stdio-safer and tmpfile
Date: Fri, 21 Jul 2006 15:51:36 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Even after using stdio-safer, m4 still has a bug where stderr can be clobbered; 
it is the third case in:
http://lists.gnu.org/archive/html/bug-m4/2006-07/msg00021.html

I traced it to the fact that we don't have tmpfile_safer.  I based my 
implementation on Paul's fopen trick, which uses at most one extra fd.  But I 
had to use "wb+" instead of "w+" on platforms where binary matters, because 
this is how newlib's tmpfile (and hence cygwin) does it.

I guess the alternative to dragging in binary-io would be that if tmpfile comes 
up with fd 0, 1, or 2, we repeatedly call tmpfile (and let the underlying 
library decide what mode tmpfile implies), at the possible expense of more 
syscalls and using up to three extra fd's before stabilizing on a good fd.

Okay to install?

ChangeLog:
2006-07-21  Eric Blake  <address@hidden>

        * modules/stdio-safer (Files): Add tmpfile-safer.c.
        (Depends-on): Add binary-io.

m4/ChangeLog
2006-07-21  Eric Blake  <address@hidden>

        * stdio-safer.m4 (gl_STDIO_SAFER): Add tmpfile-safer.c.

lib/ChangeLog
2006-07-21  Eric Blake  <address@hidden>

        * tmpfile-safer.c: New file.
        * stdio-safer.h (tmpfile_safer): Add prototype.
        * stdio--.h (tmpfile): Make safer.


Index: m4/stdio-safer.m4
===================================================================
RCS file: /sources/gnulib/gnulib/m4/stdio-safer.m4,v
retrieving revision 1.6
diff -u -r1.6 stdio-safer.m4
--- m4/stdio-safer.m4   23 Sep 2005 04:15:13 -0000      1.6
+++ m4/stdio-safer.m4   21 Jul 2006 15:36:28 -0000
@@ -1,11 +1,12 @@
-#serial 5
-dnl Copyright (C) 2002, 2005 Free Software Foundation, Inc.
+#serial 6   -*- Autoconf -*-
+dnl Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
 
 AC_DEFUN([gl_STDIO_SAFER],
 [
-  AC_LIBSOURCES([fopen-safer.c, stdio-safer.h, stdio--.h])
+  AC_LIBSOURCES([fopen-safer.c, tmpfile-safer.c, stdio-safer.h, stdio--.h])
   AC_LIBOBJ([fopen-safer])
+  AC_LIBOBJ([tmpfile-safer])
 ])
Index: modules/stdio-safer
===================================================================
RCS file: /sources/gnulib/gnulib/modules/stdio-safer,v
retrieving revision 1.6
diff -u -r1.6 stdio-safer
--- modules/stdio-safer 31 Aug 2005 15:39:48 -0000      1.6
+++ modules/stdio-safer 21 Jul 2006 15:36:28 -0000
@@ -5,9 +5,11 @@
 lib/stdio--.h
 lib/stdio-safer.h
 lib/fopen-safer.c
+lib/tmpfile-safer.c
 m4/stdio-safer.m4
 
 Depends-on:
+binary-io
 unistd-safer
 
 configure.ac:
Index: lib/stdio--.h
===================================================================
RCS file: /sources/gnulib/gnulib/lib/stdio--.h,v
retrieving revision 1.1
diff -u -r1.1 stdio--.h
--- lib/stdio--.h       27 Aug 2005 20:12:02 -0000      1.1
+++ lib/stdio--.h       21 Jul 2006 15:36:29 -0000
@@ -1,6 +1,6 @@
 /* Like stdio.h, but redefine some names to avoid glitches.
 
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -23,3 +23,6 @@
 
 #undef fopen
 #define fopen fopen_safer
+
+#undef tmpfile
+#define tmpfile tmpfile_safer
Index: lib/stdio-safer.h
===================================================================
RCS file: /sources/gnulib/gnulib/lib/stdio-safer.h,v
retrieving revision 1.4
diff -u -r1.4 stdio-safer.h
--- lib/stdio-safer.h   14 May 2005 06:03:58 -0000      1.4
+++ lib/stdio-safer.h   21 Jul 2006 15:36:29 -0000
@@ -1,6 +1,6 @@
 /* Invoke stdio functions, but avoid some glitches.
 
-   Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2006 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,3 +21,4 @@
 #include <stdio.h>
 
 FILE *fopen_safer (char const *, char const *);
+FILE *tmpfile_safer (void);
Index: lib/tmpfile-safer.c
===================================================================
RCS file: lib/tmpfile-safer.c
diff -N lib/tmpfile-safer.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/tmpfile-safer.c 21 Jul 2006 15:36:29 -0000
@@ -0,0 +1,73 @@
+/* Invoke tmpfile, but avoid some glitches.
+   Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Eric Blake, based on ideas from Paul Eggert.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "stdio-safer.h"
+
+#include <errno.h>
+#include <unistd.h>
+#include "unistd-safer.h"
+
+#include "binary-io.h"
+
+#ifndef STDERR_FILENO
+# define STDERR_FILENO 2
+#endif
+
+/* Like tmpfile, but do not return stdin, stdout, or stderr.  */
+
+FILE *
+tmpfile_safer (void)
+{
+  FILE *fp = tmpfile ();
+
+  if (fp)
+    {
+      int fd = fileno (fp);
+
+      if (0 <= fd && fd <= STDERR_FILENO)
+       {
+         int f = dup_safer (fd);
+
+         if (f < 0)
+           {
+             int e = errno;
+             fclose (fp);
+             errno = e;
+             return NULL;
+           }
+
+          /* Keep the temporary file in binary mode, on platforms where it
+             matters.  */
+         if (fclose (fp) != 0
+             || ! (fp = fdopen (f, O_BINARY ? "wb+" : "wb")))
+           {
+             int e = errno;
+             close (f);
+             errno = e;
+             return NULL;
+           }
+       }
+    }
+
+  return fp;
+}






reply via email to

[Prev in Thread] Current Thread [Next in Thread]