* NEWS: Mention ptrdiff_t. * lib/careadlinkat.c: Include stdint.h, intprops.h, minmax.h, walloc.h. (SSIZE_MAX): Use TYPE_MAXIMUM. (careadlinkat): Accept ptrdiff_t, not size_t. Use wallocmore instead of rolling our own allocator. * lib/careadlinkat.h (careadlinkat): Accept ptrdiff_t, not size_t. * modules/careadlinkat (Depends-on): Add intprops, minmax, stdint, walloc. Remove allocator. --- ChangeLog | 10 ++++++++ NEWS | 4 ++++ lib/careadlinkat.c | 64 +++++++++++++++++++--------------------------------- lib/careadlinkat.h | 2 +- modules/careadlinkat | 5 +++- 5 files changed, 42 insertions(+), 43 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 5aae016..d7e6afc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 2017-06-04 Paul Eggert <[email protected]> + careadlinkat: use walloc + * NEWS: Mention ptrdiff_t. + * lib/careadlinkat.c: Include stdint.h, intprops.h, minmax.h, walloc.h. + (SSIZE_MAX): Use TYPE_MAXIMUM. + (careadlinkat): Accept ptrdiff_t, not size_t. + Use wallocmore instead of rolling our own allocator. + * lib/careadlinkat.h (careadlinkat): Accept ptrdiff_t, not size_t. + * modules/careadlinkat (Depends-on): Add intprops, minmax, stdint, + walloc. Remove allocator. + allocator: allow reasons other than size overflow * lib/allocator.h: Adjust comment to allow reasons other than size overflow to result in SIZE_MAX. diff --git a/NEWS b/NEWS index b75ca01..ff60817 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,10 @@ User visible incompatible changes Date Modules Changes +2017-06-04 careadlinkat careadlinkat now takes + ptrdiff_t instead of size_t arguments for object + and byte counts. + 2017-05-19 closeout close_stdout longer closes stderr when addresses are being sanitized, as the sanitizer outputs to stderr afterwards. diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index 455e00e..f939b0f 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -24,19 +24,18 @@ #include <errno.h> #include <limits.h> +#include <stdint.h> #include <string.h> #include <unistd.h> -/* Define this independently so that stdint.h is not a prerequisite. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - #ifndef SSIZE_MAX -# define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) +# define SSIZE_MAX TYPE_MAXIMUM (ssize_t) #endif #include "allocator.h" +#include "intprops.h" +#include "minmax.h" +#include "walloc.h" /* Assuming the current directory is FD, get the symbolic link value of FILENAME as a null-terminated string and put it into a buffer. @@ -49,8 +48,7 @@ If the link is not small, put it into a dynamically allocated buffer managed by ALLOC. It is the caller's responsibility to free - the returned value if it is nonnull and is not BUFFER. A null - ALLOC stands for the standard allocator. + the returned value if it is nonnull and is not BUFFER. The PREADLINKAT function specifies how to read links. It operates like POSIX readlinkat() @@ -62,19 +60,15 @@ char * careadlinkat (int fd, char const *filename, - char *buffer, size_t buffer_size, + char *buffer, ptrdiff_t buffer_size, struct allocator const *alloc, ssize_t (*preadlinkat) (int, char const *, char *, size_t)) { char *buf; - size_t buf_size; - size_t buf_size_max = - SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; + ptrdiff_t buf_size; + ptrdiff_t buf_size_max = MIN (PTRDIFF_MAX, SSIZE_MAX); char stack_buf[1024]; - if (! alloc) - alloc = &stdlib_allocator; - if (! buffer_size) { /* Allocate the initial buffer on the stack. This way, in the @@ -92,7 +86,6 @@ careadlinkat (int fd, char const *filename, { /* Attempt to read the link into the current buffer. */ ssize_t link_length = preadlinkat (fd, filename, buf, buf_size); - size_t link_size; if (link_length < 0) { /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1 @@ -108,26 +101,27 @@ careadlinkat (int fd, char const *filename, return NULL; } } - - link_size = link_length; - - if (link_size < buf_size) + else if (link_length < buf_size) { - buf[link_size++] = '\0'; + buf[link_length++] = '\0'; if (buf == stack_buf) { - char *b = (char *) alloc->allocate (link_size); - buf_size = link_size; + char *b = alloc->allocate (link_length); if (! b) - break; - memcpy (b, buf, link_size); + { + if (alloc->die) + alloc->die (link_length); + break; + } + memcpy (b, buf, link_length); buf = b; + buf_size = link_length; } - else if (link_size < buf_size && buf != buffer && alloc->reallocate) + else if (buf != buffer) { /* Shrink BUF before returning it. */ - char *b = (char *) alloc->reallocate (buf, link_size); + char *b = alloc->reallocate (buf, link_length); if (b) buf = b; } @@ -138,23 +132,11 @@ careadlinkat (int fd, char const *filename, if (buf != buffer) alloc->free (buf); - if (buf_size <= buf_size_max / 2) - buf_size *= 2; - else if (buf_size < buf_size_max) - buf_size = buf_size_max; - else if (buf_size_max < SIZE_MAX) - { - errno = ENAMETOOLONG; - return NULL; - } - else - break; - buf = (char *) alloc->allocate (buf_size); + /* BUF_SIZE was not big enough; try again with a larger value. */ + buf = wallocmore (NULL, &buf_size, 1, buf_size_max, sizeof *buf, alloc); } while (buf); - if (alloc->die) - alloc->die (buf_size); errno = ENOMEM; return NULL; } diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h index 528a828..b66e4bd 100644 --- a/lib/careadlinkat.h +++ b/lib/careadlinkat.h @@ -47,7 +47,7 @@ struct allocator; set errno. */ char *careadlinkat (int fd, char const *filename, - char *buffer, size_t buffer_size, + char *buffer, ptrdiff_t buffer_size, struct allocator const *alloc, ssize_t (*preadlinkat) (int, char const *, char *, size_t)); diff --git a/modules/careadlinkat b/modules/careadlinkat index 9dd7471..5079429 100644 --- a/modules/careadlinkat +++ b/modules/careadlinkat @@ -6,9 +6,12 @@ lib/careadlinkat.c lib/careadlinkat.h Depends-on: -allocator +intprops +minmax ssize_t +stdint unistd +walloc configure.ac: AC_CHECK_FUNCS_ONCE([readlinkat]) -- 2.9.4
