From 63a51f5a37634098883aa83d78be90e5dffcd9ce Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 23 Apr 2017 02:45:19 +0200 Subject: [PATCH] getlogin_r: Work around bug in Mac OS X 10.12. * m4/getlogin_r.m4 (gl_FUNC_GETLOGIN_R): Test also against the Mac OS X bug. * lib/getlogin_r.c (getlogin_r): When getlogin_r returns a string of the given size minus 1, call getlogin_r a second time, on a larger buffer. * modules/getlogin_r (Depends-on): Add malloca. * doc/posix-functions/getlogin_r.texi: Mention the Mac OS X bug. --- ChangeLog | 10 ++++++++++ doc/posix-functions/getlogin_r.texi | 2 +- lib/getlogin_r.c | 26 ++++++++++++++++++++++--- m4/getlogin_r.m4 | 30 ++++++++++++++++------------- modules/getlogin_r | 1 + 5 files changed, 52 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index bdebb94589..25fe006255 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2017-04-22 Bruno Haible + + getlogin_r: Work around bug in Mac OS X 10.12. + * m4/getlogin_r.m4 (gl_FUNC_GETLOGIN_R): Test also against the Mac OS X + bug. + * lib/getlogin_r.c (getlogin_r): When getlogin_r returns a string of the + given size minus 1, call getlogin_r a second time, on a larger buffer. + * modules/getlogin_r (Depends-on): Add malloca. + * doc/posix-functions/getlogin_r.texi: Mention the Mac OS X bug. + 2017-04-22 Paul Eggert parse-datetime: fix %z and prefer signed int diff --git a/doc/posix-functions/getlogin_r.texi b/doc/posix-functions/getlogin_r.texi index 6efb9771ea..09aa5f1667 100644 --- a/doc/posix-functions/getlogin_r.texi +++ b/doc/posix-functions/getlogin_r.texi @@ -18,7 +18,7 @@ HP-UX 11. @item This function returns a truncated result, instead of failing with error code @code{ERANGE}, when the buffer is not large enough, on some platforms: -OSF/1 5.1. +Mac OS X 10.12, OSF/1 5.1. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/getlogin_r.c b/lib/getlogin_r.c index 352b0413db..230aba0ef5 100644 --- a/lib/getlogin_r.c +++ b/lib/getlogin_r.c @@ -25,6 +25,8 @@ #include #include +#include "malloca.h" + #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ # define WIN32_LEAN_AND_MEAN # include @@ -63,9 +65,27 @@ getlogin_r (char *name, size_t size) /* Platform with a getlogin_r() function. */ int ret = getlogin_r (name, size); - if (ret == 0 && memchr (name, '\0', size) == NULL) - /* name contains a truncated result. */ - return ERANGE; + if (ret == 0) + { + const char *nul = memchr (name, '\0', size); + if (nul == NULL) + /* name contains a truncated result. */ + return ERANGE; + if (size > 0 && nul == name + size - 1) + { + /* strlen(name) == size-1. Determine whether the untruncated result + would have had length size-1 or size. */ + char *room = (char *) malloca (size + 1); + if (room == NULL) + return ENOMEM; + ret = getlogin_r (room, size + 1); + /* The untruncated result should be the same as in the first call. */ + if (ret == 0 && memcmp (name, room, size) != 0) + /* The untruncated result would have been different. */ + ret = ERANGE; + freea (room); + } + } return ret; #else /* Platform with a getlogin() function. */ diff --git a/m4/getlogin_r.m4 b/m4/getlogin_r.m4 index 597bcd00ba..c00a13e0f1 100644 --- a/m4/getlogin_r.m4 +++ b/m4/getlogin_r.m4 @@ -1,4 +1,4 @@ -#serial 11 +#serial 12 # Copyright (C) 2005-2007, 2009-2017 Free Software Foundation, Inc. # @@ -30,8 +30,8 @@ AC_DEFUN([gl_FUNC_GETLOGIN_R], HAVE_GETLOGIN_R=0 else HAVE_GETLOGIN_R=1 - dnl On OSF/1 5.1, getlogin_r returns a truncated result if the buffer is - dnl not large enough. + dnl On Mac OS X 10.12 and OSF/1 5.1, getlogin_r returns a truncated result + dnl if the buffer is not large enough. AC_REQUIRE([AC_CANONICAL_HOST]) AC_CACHE_CHECK([whether getlogin_r works with small buffers], [gl_cv_func_getlogin_r_works], @@ -39,15 +39,16 @@ AC_DEFUN([gl_FUNC_GETLOGIN_R], dnl Initial guess, used when cross-compiling. changequote(,)dnl case "$host_os" in - # Guess no on OSF/1. - osf*) gl_cv_func_getlogin_r_works="guessing no" ;; - # Guess yes otherwise. - *) gl_cv_func_getlogin_r_works="guessing yes" ;; + # Guess no on Mac OS X, OSF/1. + darwin* | osf*) gl_cv_func_getlogin_r_works="guessing no" ;; + # Guess yes otherwise. + *) gl_cv_func_getlogin_r_works="guessing yes" ;; esac changequote([,])dnl AC_RUN_IFELSE( [AC_LANG_SOURCE([[ #include +#include #include #if !HAVE_DECL_GETLOGIN_R extern @@ -63,16 +64,19 @@ main (void) char buf[100]; if (getlogin_r (buf, 0) == 0) - result |= 16; + result |= 1; if (getlogin_r (buf, 1) == 0) - result |= 17; + result |= 2; + if (getlogin_r (buf, 100) == 0) + { + size_t n = strlen (buf); + if (getlogin_r (buf, n) == 0) + result |= 4; + } return result; }]])], [gl_cv_func_getlogin_r_works=yes], - [case $? in - 16 | 17) gl_cv_func_getlogin_r_works=no ;; - esac - ], + [gl_cv_func_getlogin_r_works=no], [:]) ]) case "$gl_cv_func_getlogin_r_works" in diff --git a/modules/getlogin_r b/modules/getlogin_r index 169cb441a2..befc365544 100644 --- a/modules/getlogin_r +++ b/modules/getlogin_r @@ -9,6 +9,7 @@ m4/getlogin.m4 Depends-on: unistd extensions +malloca [test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1] memchr [test $HAVE_GETLOGIN_R = 0 || test $REPLACE_GETLOGIN_R = 1] configure.ac: -- 2.39.5