From 3e4a348ea6f027e6337a9d0709e7f32422f04f19 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Tue, 2 Jul 2019 20:43:00 +0200 Subject: [PATCH] getcwd: Fix crash when invoked with size = 0 on MSVC. * lib/getcwd.c: Include msvc-inval.h. (getcwd_nothrow): New function/macro. (getcwd_system): New macro. (__getcwd): Use it instead of getcwd. * modules/getcwd (Depends-on): Add msvc-inval. * doc/posix-functions/getcwd.texi: Mention the MSVC issue. --- ChangeLog | 10 +++++++++ doc/posix-functions/getcwd.texi | 5 ++++- lib/getcwd.c | 36 +++++++++++++++++++++++++++++++-- modules/getcwd | 1 + 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 706fe6a771..7b3d3bdeb7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2019-07-02 Bruno Haible + + getcwd: Fix crash when invoked with size = 0 on MSVC. + * lib/getcwd.c: Include msvc-inval.h. + (getcwd_nothrow): New function/macro. + (getcwd_system): New macro. + (__getcwd): Use it instead of getcwd. + * modules/getcwd (Depends-on): Add msvc-inval. + * doc/posix-functions/getcwd.texi: Mention the MSVC issue. + 2019-07-02 Bruno Haible nonblocking-pipe tests: Fix test failure on MSVC. diff --git a/doc/posix-functions/getcwd.texi b/doc/posix-functions/getcwd.texi index 07025695d4..41e19c58b9 100644 --- a/doc/posix-functions/getcwd.texi +++ b/doc/posix-functions/getcwd.texi @@ -23,9 +23,12 @@ instead of @code{size_t} for the size argument when using non-standard headers, and the declaration is missing from @code{}: mingw, MSVC 14. @item +On some platforms, @code{getcwd (buf, 0)} crashes: +MSVC 14. +@item On some platforms, @code{getcwd (buf, 0)} fails with @code{ERANGE} instead of the required @code{EINVAL}: -mingw, MSVC 14. +mingw. @end itemize Portability problems fixed by Gnulib module @code{getcwd}: diff --git a/lib/getcwd.c b/lib/getcwd.c index 41eedb7005..8f15f560c2 100644 --- a/lib/getcwd.c +++ b/lib/getcwd.c @@ -79,6 +79,10 @@ # define MATCHING_INO(dp, ino) true #endif +#if HAVE_MSVC_INVALID_PARAMETER_HANDLER +# include "msvc-inval.h" +#endif + #if !_LIBC # define __getcwd rpl_getcwd # define __lstat lstat @@ -100,6 +104,34 @@ # undef closedir #endif +#ifdef _MSC_VER +# if HAVE_MSVC_INVALID_PARAMETER_HANDLER +static char * +getcwd_nothrow (char *buf, size_t size) +{ + char *result; + + TRY_MSVC_INVAL + { + result = _getcwd (buf, size); + } + CATCH_MSVC_INVAL + { + result = NULL; + errno = ERANGE; + } + DONE_MSVC_INVAL; + + return result; +} +# else +# define getcwd_nothrow _getcwd +# endif +# define getcwd_system getcwd_nothrow +#else +# define getcwd_system getcwd +#endif + /* Get the name of the current working directory, and put it in SIZE bytes of BUF. Returns NULL if the directory couldn't be determined or SIZE was too small. If successful, returns BUF. In GNU, if BUF is @@ -155,7 +187,7 @@ __getcwd (char *buf, size_t size) this wrong result with errno = 0. */ # undef getcwd - dir = getcwd (buf, size); + dir = getcwd_system (buf, size); if (dir || (size && errno == ERANGE)) return dir; @@ -166,7 +198,7 @@ __getcwd (char *buf, size_t size) if (errno == EINVAL && buf == NULL && size == 0) { char big_buffer[BIG_FILE_NAME_LENGTH + 1]; - dir = getcwd (big_buffer, sizeof big_buffer); + dir = getcwd_system (big_buffer, sizeof big_buffer); if (dir) return strdup (dir); } diff --git a/modules/getcwd b/modules/getcwd index 628c4d1f6f..90299a1c7e 100644 --- a/modules/getcwd +++ b/modules/getcwd @@ -13,6 +13,7 @@ Depends-on: unistd extensions pathmax [test $REPLACE_GETCWD = 1] +msvc-inval [test $REPLACE_GETCWD = 1] mempcpy [test $REPLACE_GETCWD = 1] d-ino [test $REPLACE_GETCWD = 1] memmove [test $REPLACE_GETCWD = 1] -- 2.39.5