From: Paul Eggert Date: Fri, 12 Jan 2007 21:54:50 +0000 (+0000) Subject: * lib/xreadlink.c (SYMLINK_MAX) [!defined SYMLINK_MAX]: Define X-Git-Tag: cvs-readonly~1359 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=662e273931461d8aed89f64ea9ceb1618916e180;p=gnulib.git * lib/xreadlink.c (SYMLINK_MAX) [!defined SYMLINK_MAX]: Define to a reasonable default for memory allocation. (xreadlink): Don't allocate a huge buffer, to work around a buggy file system that reports garbage st_size values for symlinks. Problem reported by Liyang Hu. --- diff --git a/ChangeLog b/ChangeLog index 6e7203b01..66fda758f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2007-01-12 Paul Eggert + + * lib/xreadlink.c (SYMLINK_MAX) [!defined SYMLINK_MAX]: Define + to a reasonable default for memory allocation. + (xreadlink): Don't allocate a huge buffer, to work around a buggy + file system that reports garbage st_size values for symlinks. + Problem reported by Liyang Hu. + 2007-01-11 Simon Josefsson * gnulib-tool (func_all_modules): Exclude all .* files (e.g., diff --git a/lib/xreadlink.c b/lib/xreadlink.c index 8d61b633a..baea5b9cf 100644 --- a/lib/xreadlink.c +++ b/lib/xreadlink.c @@ -38,6 +38,13 @@ # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif +/* SYMLINK_MAX is used only for an initial memory-allocation sanity + check, so it's OK to guess too small on hosts where there is no + arbitrary limit to symbolic link length. */ +#ifndef SYMLINK_MAX +# define SYMLINK_MAX 1024 +#endif + #define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX) #include "xalloc.h" @@ -53,9 +60,17 @@ char * xreadlink (char const *file, size_t size) { - /* The initial buffer size for the link value. A power of 2 - detects arithmetic overflow earlier, but is not required. */ - size_t buf_size = size < MAXSIZE ? size + 1 : MAXSIZE; + /* Some buggy file systems report garbage in st_size. Defend + against them by ignoring outlandish st_size values in the initial + memory allocation. */ + size_t symlink_max = SYMLINK_MAX; + size_t INITIAL_LIMIT_BOUND = 8 * 1024; + size_t initial_limit = (symlink_max < INITIAL_LIMIT_BOUND + ? symlink_max + 1 + : INITIAL_LIMIT_BOUND); + + /* The initial buffer size for the link value. */ + size_t buf_size = size < initial_limit ? size + 1 : initial_limit; while (1) {