The dup() function also crashes on MSVC 9 if an invalid argument is passed. This new module 'dup' fixes it.
2011-09-23 Bruno Haible <br...@clisp.org> New module 'dup'. * lib/unistd.in.h (dup): Declare only if the 'dup' module is in use. Allow replacement. * lib/dup.c: New file. * lib/fchdir.c (rpl_dup): Remove function. * m4/dup.m4: New file. * m4/fchdir.m4 (gl_FUNC_FCHDIR): Don't set REPLACE_DUP here. * m4/unistd_h.m4 (gl_UNISTD_H): Test whether 'dup' is declared. (gl_UNISTD_H_DEFAULTS): Initialize GNULIB_DUP. * modules/unistd (Makefile.am): Substitute GNULIB_DUP. * modules/dup: New file. * tests/test-unistd-c++.cc: Check the signature of 'dup' only if the 'dup' module is in use. * modules/fdopendir (Depends-on): Add dup. * modules/fdutimensat-tests (Depends-on): Likewise. * modules/fts (Depends-on): Likewise. * modules/futimens-tests (Depends-on): Likewise. * modules/posix_spawnp-tests (Depends-on): Likewise. * modules/unistd-safer-tests (Depends-on): Likewise. * modules/utimens-tests (Depends-on): Likewise. * doc/posix-functions/dup.texi: Mention the new module and the problem on MSVC. ================================== lib/dup.c ================================== /* Duplicate an open file descriptor. Copyright (C) 2011 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 3 of the License, 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, see <http://www.gnu.org/licenses/>. */ #include <config.h> /* Specification. */ #include <unistd.h> #include <errno.h> #include "msvc-inval.h" #undef dup #if HAVE_MSVC_INVALID_PARAMETER_HANDLER static inline int dup_nothrow (int fd) { int result; TRY_MSVC_INVAL { result = dup (fd); } CATCH_MSVC_INVAL { result = -1; errno = EBADF; } DONE_MSVC_INVAL; return result; } #else # define dup_nothrow dup #endif int rpl_dup (int fd) { int result = dup_nothrow (fd); #if REPLACE_FCHDIR if (result >= 0) result = _gl_register_dup (fd, result); #endif return result; } ================================== m4/dup.m4 ================================== # dup.m4 serial 1 dnl Copyright (C) 2011 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_FUNC_DUP], [ AC_REQUIRE([gl_UNISTD_H_DEFAULTS]) AC_REQUIRE([AC_CANONICAL_HOST]) AC_CHECK_HEADERS_ONCE([unistd.h]) AC_CACHE_CHECK([whether dup supports bad arguments], [gl_cv_func_dup_works], [AC_RUN_IFELSE( [AC_LANG_PROGRAM([[ #if HAVE_UNISTD_H # include <unistd.h> #else # include <io.h> #endif #include <errno.h> ]], [[if (dup (-1) != -1) return 1; if (errno != EBADF) return 2; return 0; ]])], [gl_cv_func_dup_works=yes], [gl_cv_func_dup_works=no], [case "$host_os" in mingw*) gl_cv_func_dup_works="guessing no" ;; *) gl_cv_func_dup_works="guessing yes" ;; esac ]) ]) case "$gl_cv_func_dup_works" in *no) REPLACE_DUP=1 ;; esac dnl Replace dup() for supporting the gnulib-defined fchdir() function, dnl to keep fchdir's bookkeeping up-to-date. m4_ifdef([gl_FUNC_FCHDIR], [ gl_TEST_FCHDIR if test $HAVE_FCHDIR = 0; then REPLACE_DUP=1 fi ]) ]) # Prerequisites of lib/dup.c. AC_DEFUN([gl_PREREQ_DUP], [ AC_REQUIRE([AC_C_INLINE]) ]) ================================= modules/dup ================================= Description: dup() function: duplicate an open file descriptor. Files: lib/dup.c m4/dup.m4 Depends-on: unistd msvc-inval [test $REPLACE_DUP = 1] configure.ac: gl_FUNC_DUP if test $REPLACE_DUP = 1; then AC_LIBOBJ([dup]) gl_PREREQ_DUP fi gl_UNISTD_MODULE_INDICATOR([dup]) Makefile.am: Include: <unistd.h> License: LGPLv2+ Maintainer: Bruno Haible =============================================================================== --- doc/posix-functions/dup.texi.orig Sat Sep 24 02:06:57 2011 +++ doc/posix-functions/dup.texi Fri Sep 23 22:03:29 2011 @@ -4,10 +4,13 @@ POSIX specification:@* @url{http://www.opengroup.org/onlinepubs/9699919799/functions/dup.html} -Gnulib module: --- +Gnulib module: dup Portability problems fixed by Gnulib: @itemize +@item +This function crashes when invoked with invalid arguments on some platforms: +MSVC 9. @end itemize Portability problems not fixed by Gnulib: --- lib/fchdir.c.orig Sat Sep 24 02:06:57 2011 +++ lib/fchdir.c Fri Sep 23 22:03:29 2011 @@ -211,19 +211,6 @@ } #endif -/* Override dup(), to keep track of open file descriptors. */ - -int -rpl_dup (int oldfd) -#undef dup -{ - int newfd = dup (oldfd); - - if (0 <= newfd) - newfd = _gl_register_dup (oldfd, newfd); - return newfd; -} - /* Implement fchdir() in terms of chdir(). */ --- lib/unistd.in.h.orig Sat Sep 24 02:06:57 2011 +++ lib/unistd.in.h Fri Sep 23 22:03:29 2011 @@ -301,16 +301,24 @@ #endif -#if @REPLACE_DUP@ -# if !(defined __cplusplus && defined GNULIB_NAMESPACE) -# define dup rpl_dup -# endif +#if @GNULIB_DUP@ +# if @REPLACE_DUP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define dup rpl_dup +# endif _GL_FUNCDECL_RPL (dup, int, (int oldfd)); _GL_CXXALIAS_RPL (dup, int, (int oldfd)); -#else +# else _GL_CXXALIAS_SYS (dup, int, (int oldfd)); -#endif +# endif _GL_CXXALIASWARN (dup); +#elif defined GNULIB_POSIXCHECK +# undef dup +# if HAVE_RAW_DECL_DUP +_GL_WARN_ON_USE (dup, "dup is unportable - " + "use gnulib module dup for portability"); +# endif +#endif #if @GNULIB_DUP2@ --- m4/fchdir.m4.orig Sat Sep 24 02:06:57 2011 +++ m4/fchdir.m4 Fri Sep 23 22:03:29 2011 @@ -1,4 +1,4 @@ -# fchdir.m4 serial 18 +# fchdir.m4 serial 19 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -24,7 +24,6 @@ dnl We must also replace anything that can manipulate a directory fd, dnl to keep our bookkeeping up-to-date. We don't have to replace dnl fstatat, since no platform has fstatat but lacks fchdir. - REPLACE_DUP=1 AC_CACHE_CHECK([whether open can visit directories], [gl_cv_func_open_directory_works], [AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <fcntl.h> --- m4/unistd_h.m4.orig Sat Sep 24 02:06:57 2011 +++ m4/unistd_h.m4 Fri Sep 23 22:03:29 2011 @@ -1,4 +1,4 @@ -# unistd_h.m4 serial 60 +# unistd_h.m4 serial 61 dnl Copyright (C) 2006-2011 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -39,7 +39,7 @@ # include <io.h> # endif #endif - ]], [chdir chown dup2 dup3 environ euidaccess faccessat fchdir fchownat + ]], [chdir chown dup dup2 dup3 environ euidaccess faccessat fchdir fchownat fdatasync fsync ftruncate getcwd getdomainname getdtablesize getgroups gethostname getlogin getlogin_r getpagesize getusershell setusershell endusershell group_member lchown link linkat lseek pipe pipe2 pread pwrite @@ -61,6 +61,7 @@ GNULIB_CHDIR=0; AC_SUBST([GNULIB_CHDIR]) GNULIB_CHOWN=0; AC_SUBST([GNULIB_CHOWN]) GNULIB_CLOSE=0; AC_SUBST([GNULIB_CLOSE]) + GNULIB_DUP=0; AC_SUBST([GNULIB_DUP]) GNULIB_DUP2=0; AC_SUBST([GNULIB_DUP2]) GNULIB_DUP3=0; AC_SUBST([GNULIB_DUP3]) GNULIB_ENVIRON=0; AC_SUBST([GNULIB_ENVIRON]) --- modules/fdopendir.orig Sat Sep 24 02:06:57 2011 +++ modules/fdopendir Fri Sep 23 22:03:29 2011 @@ -10,6 +10,7 @@ Depends-on: dirent extensions +dup [test $HAVE_FDOPENDIR = 0] errno [test $HAVE_FDOPENDIR = 0] fchdir [test $HAVE_FDOPENDIR = 0] openat-die [test $HAVE_FDOPENDIR = 0] --- modules/fdutimensat-tests.orig Sat Sep 24 02:06:57 2011 +++ modules/fdutimensat-tests Fri Sep 23 22:03:29 2011 @@ -10,6 +10,7 @@ Depends-on: ignore-value timespec +dup usleep utimecmp --- modules/fts.orig Sat Sep 24 02:06:57 2011 +++ modules/fts Fri Sep 23 22:03:29 2011 @@ -14,6 +14,7 @@ d-ino d-type dirent-safer +dup fchdir fcntl-h fcntl-safer --- modules/futimens-tests.orig Sat Sep 24 02:06:57 2011 +++ modules/futimens-tests Fri Sep 23 22:03:29 2011 @@ -9,6 +9,7 @@ Depends-on: ignore-value timespec +dup usleep utimecmp --- modules/posix_spawnp-tests.orig Sat Sep 24 02:06:57 2011 +++ modules/posix_spawnp-tests Fri Sep 23 22:03:29 2011 @@ -19,6 +19,7 @@ stdbool unistd sys_wait +dup configure.ac: AC_EGREP_CPP([notposix], [[ --- modules/unistd.orig Sat Sep 24 02:06:57 2011 +++ modules/unistd Fri Sep 23 22:03:29 2011 @@ -33,6 +33,7 @@ -e 's/@''GNULIB_CHDIR''@/$(GNULIB_CHDIR)/g' \ -e 's/@''GNULIB_CHOWN''@/$(GNULIB_CHOWN)/g' \ -e 's/@''GNULIB_CLOSE''@/$(GNULIB_CLOSE)/g' \ + -e 's/@''GNULIB_DUP''@/$(GNULIB_DUP)/g' \ -e 's/@''GNULIB_DUP2''@/$(GNULIB_DUP2)/g' \ -e 's/@''GNULIB_DUP3''@/$(GNULIB_DUP3)/g' \ -e 's/@''GNULIB_ENVIRON''@/$(GNULIB_ENVIRON)/g' \ --- modules/unistd-safer-tests.orig Sat Sep 24 02:06:57 2011 +++ modules/unistd-safer-tests Fri Sep 23 22:03:29 2011 @@ -5,6 +5,7 @@ Depends-on: binary-io cloexec +dup fd-safer-flag msvc-nothrow stdbool --- modules/utimens-tests.orig Sat Sep 24 02:06:57 2011 +++ modules/utimens-tests Fri Sep 23 22:03:29 2011 @@ -8,6 +8,7 @@ tests/macros.h Depends-on: +dup ignore-value symlink timespec --- tests/test-unistd-c++.cc.orig Sat Sep 24 02:06:57 2011 +++ tests/test-unistd-c++.cc Fri Sep 23 22:03:29 2011 @@ -36,7 +36,9 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::close, int, (int)); #endif +#if GNULIB_TEST_DUP SIGNATURE_CHECK (GNULIB_NAMESPACE::dup, int, (int)); +#endif #if GNULIB_TEST_DUP2 SIGNATURE_CHECK (GNULIB_NAMESPACE::dup2, int, (int, int)); -- In memoriam Ghazala Khan <http://en.wikipedia.org/wiki/Ghazala_Khan>