diff options
author | Jim Meyering <jim@meyering.net> | 2006-06-18 21:52:03 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 2006-06-18 21:52:03 +0000 |
commit | 48d2f622135c22a99f5733f8019dfc261aaf4058 (patch) | |
tree | 3ec2847190875b33782378cb8a48ce768616a318 /m4 | |
parent | a40e199756443e32e68db0a9686a662a97af8b30 (diff) | |
download | coreutils-48d2f622135c22a99f5733f8019dfc261aaf4058.tar.xz |
Test for a bug that causes glibc's getcwd to suffer a failed assertion.
* getcwd-abort-bug.m4 (gl_FUNC_GETCWD_ABORT_BUG): New file and macro.
* getcwd.m4 (gl_FUNC_GETCWD): If we detect support for getcwd_null,
also check for glibc-2.4's abort-inducing bug.
Diffstat (limited to 'm4')
-rw-r--r-- | m4/ChangeLog | 5 | ||||
-rw-r--r-- | m4/getcwd-abort-bug.m4 | 106 | ||||
-rw-r--r-- | m4/getcwd.m4 | 11 |
3 files changed, 118 insertions, 4 deletions
diff --git a/m4/ChangeLog b/m4/ChangeLog index ced95ddf2..2fc9a180b 100644 --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,5 +1,10 @@ 2006-06-18 Jim Meyering <jim@meyering.net> + Test for a bug that causes glibc's getcwd to suffer a failed assertion. + * getcwd-abort-bug.m4 (gl_FUNC_GETCWD_ABORT_BUG): New file and macro. + * getcwd.m4 (gl_FUNC_GETCWD): If we detect support for getcwd_null, + also check for glibc-2.4's abort-inducing bug. + * getcwd-path-max.m4 (gl_FUNC_GETCWD_PATH_MAX): Fix typo. Low-probability clean-up should be to use rmdir to get rid of the just-created directory, not unlink. diff --git a/m4/getcwd-abort-bug.m4 b/m4/getcwd-abort-bug.m4 new file mode 100644 index 000000000..a431a7ccc --- /dev/null +++ b/m4/getcwd-abort-bug.m4 @@ -0,0 +1,106 @@ +#serial 1 +# Determine whether getcwd aborts when the length of the working directory +# name is unusually large. Any length between 4k and 16k trigger the bug +# when using glibc-2.4.90-9 or older. + +# Copyright (C) 2006 Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# From Jim Meyering + +# gl_FUNC_GETCWD_ABORT_BUG([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) +AC_DEFUN([gl_FUNC_GETCWD_ABORT_BUG], +[ + AC_CHECK_DECLS_ONCE(getcwd) + AC_CHECK_FUNCS(getpagesize) + AC_CACHE_CHECK([whether getcwd aborts when 4k < cwd_length < 16k], + gl_cv_func_getcwd_abort_bug, + [# Remove any remnants of a previous test. + rm -rf confdir-14B--- + # Arrange for deletion of the temporary directory this test creates. + ac_clean_files="$ac_clean_files confdir-14B---" + AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[ +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> +#include <sys/stat.h> + +/* Don't get link errors because mkdir is redefined to rpl_mkdir. */ +#undef mkdir + +#ifndef S_IRWXU +# define S_IRWXU 0700 +#endif + +/* FIXME: skip the run-test altogether on systems without getpagesize. */ +#if ! HAVE_GETPAGESIZE +# define getpagesize() 0 +#endif + +/* This size is chosen to be larger than PATH_MAX (4k), yet smaller than + the 16kB pagesize on ia64 linux. Those conditions make the code below + trigger a bug in glibc's getcwd implementation before 2.4.90-10. */ +#define TARGET_LEN (5 * 1024) + +int +main () +{ + char const *dir_name = "confdir-14B---"; + char *cwd; + size_t initial_cwd_len; + int fail = 0; + size_t desired_depth; + size_t d; + + /* The bug is triggered when PATH_MAX < getpagesize (), so skip + this relative expensive and invasive test if that's not true. */ + if (getpagesize () <= PATH_MAX) + return 0; + + cwd = getcwd (NULL, 0); + if (cwd == NULL) + return 0; + + initial_cwd_len = strlen (cwd); + free (cwd); + desired_depth = ((TARGET_LEN - 1 - initial_cwd_len) + / (1 + strlen (dir_name))); + for (d = 0; d < desired_depth; d++) + { + if (mkdir (dir_name, S_IRWXU) < 0 || chdir (dir_name) < 0) + { + fail = 3; /* Unable to construct deep hierarchy. */ + break; + } + } + + /* If libc has the bug in question, this invocation of getcwd + results in a failed assertion. */ + cwd = getcwd (NULL, 0); + if (cwd == NULL) + fail = 4; /* getcwd failed. This is ok, and expected. */ + free (cwd); + + /* Call rmdir first, in case the above chdir failed. */ + rmdir (dir_name); + while (0 < d--) + { + if (chdir ("..") < 0) + break; + rmdir (dir_name); + } + + return 0; +} + ]])], + [gl_cv_func_getcwd_abort_bug=no], + [gl_cv_func_getcwd_abort_bug=yes], + [gl_cv_func_getcwd_abort_bug=yes]) + ]) + AS_IF([test $gl_cv_func_getcwd_abort_bug = yes], [$1], [$2]) +]) diff --git a/m4/getcwd.m4 b/m4/getcwd.m4 index 35d0b53bd..8f17432b5 100644 --- a/m4/getcwd.m4 +++ b/m4/getcwd.m4 @@ -1,6 +1,6 @@ # getcwd.m4 - check for working getcwd that is compatible with glibc -# Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -40,12 +40,15 @@ AC_DEFUN([gl_FUNC_GETCWD], [ AC_REQUIRE([gl_FUNC_GETCWD_NULL]) + gl_abort_bug=no case $gl_cv_func_getcwd_null in - yes) gl_FUNC_GETCWD_PATH_MAX;; + yes) + gl_FUNC_GETCWD_PATH_MAX + gl_FUNC_GETCWD_ABORT_BUG([gl_abort_bug=yes]);; esac - case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_path_max in - yes,yes) ;; + case $gl_cv_func_getcwd_null,$gl_cv_func_getcwd_path_max,$gl_abort_bug in + yes,yes,no) ;; *) AC_LIBOBJ([getcwd]) AC_DEFINE([__GETCWD_PREFIX], [[rpl_]], |