diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2004-11-02 20:17:37 +0000 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2004-11-02 20:17:37 +0000 |
commit | 3bd23802ad65a4379e0c97d736dc6c2ab2d37f1d (patch) | |
tree | dc8e1c28f6b4170a0813b14a0163d1fede51cf2a /lib/xreadlink.c | |
parent | ea6305f7467ea99eac90af5717e190bdffd664ce (diff) | |
download | gnulib-3bd23802ad65a4379e0c97d736dc6c2ab2d37f1d.tar.gz |
(MAXSIZE): New macro.
(xreadlink): Use it instead of SSIZE_MAX. Ensure initial buffer
size does not exceed MAXSIZE. Avoid cast.
As suggested by Mark D. Baushke in
<http://lists.gnu.org/archive/html/bug-gnulib/2004-11/msg00009.html>,
if readlink fails with buffer size just under MAXSIZE, try again
with MAXSIZE.
Diffstat (limited to 'lib/xreadlink.c')
-rw-r--r-- | lib/xreadlink.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/lib/xreadlink.c b/lib/xreadlink.c index 2e66c07f24..c38e2d3aad 100644 --- a/lib/xreadlink.c +++ b/lib/xreadlink.c @@ -41,6 +41,8 @@ # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif +#define MAXSIZE (SIZE_MAX < SSIZE_MAX ? SIZE_MAX : SSIZE_MAX) + #include "xalloc.h" /* Call readlink to get the symbolic link value of FILENAME. @@ -56,14 +58,15 @@ xreadlink (char const *filename, 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 + 1; + size_t buf_size = size < MAXSIZE ? size + 1 : MAXSIZE; while (1) { char *buffer = xmalloc (buf_size); - ssize_t link_length = readlink (filename, buffer, buf_size); + ssize_t r = readlink (filename, buffer, buf_size); + size_t link_length = r; - if (link_length < 0) + if (r < 0) { int saved_errno = errno; free (buffer); @@ -71,15 +74,18 @@ xreadlink (char const *filename, size_t size) return NULL; } - if ((size_t) link_length < buf_size) + if (link_length < buf_size) { buffer[link_length] = 0; return buffer; } free (buffer); - buf_size *= 2; - if (! (0 < buf_size && buf_size <= SSIZE_MAX)) + if (buf_size <= MAXSIZE / 2) + buf_size *= 2; + else if (buf_size < MAXSIZE) + buf_size = MAXSIZE; + else xalloc_die (); } } |