diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2021-04-21 11:03:39 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2021-04-21 11:10:48 -0700 |
commit | 87e2ea351c7e754cc3df8f6c9c519aa9fd1559e2 (patch) | |
tree | c52d7d8965577422a31580abb0fdcd830b2d3b97 | |
parent | 84b9d95e6a8f847da287c3bcd028b74a12e2f36d (diff) | |
download | gnulib-87e2ea351c7e754cc3df8f6c9c519aa9fd1559e2.tar.gz gnulib-87e2ea351c7e754cc3df8f6c9c519aa9fd1559e2.tar.bz2 |
careadlinkat: avoid ptrdiff_t overflow
* lib/careadlinkat.c: Include idx.h, minmax.h.
(readlink_stk): Avoid ptrdiff_t overflow in object allocation.
Since this module uses arbitrary allocators (including
stdlib_allocator), it cannot assume GNU malloc semantics.
* modules/careadlinkat (Depends-on): Add idx, minmax.
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | lib/careadlinkat.c | 28 | ||||
-rw-r--r-- | modules/careadlinkat | 2 |
3 files changed, 20 insertions, 17 deletions
@@ -1,5 +1,12 @@ 2021-04-21 Paul Eggert <eggert@cs.ucla.edu> + careadlinkat: avoid ptrdiff_t overflow + * lib/careadlinkat.c: Include idx.h, minmax.h. + (readlink_stk): Avoid ptrdiff_t overflow in object allocation. + Since this module uses arbitrary allocators (including + stdlib_allocator), it cannot assume GNU malloc semantics. + * modules/careadlinkat (Depends-on): Add idx, minmax. + execute-tests: pacify compiler * tests/test-execute-main.c (main): Use 0x7DEADBEE rather than 0xDEADBEEF for nonces, to avoid provoking AIX XLC compiler warning diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index 18cfc114b6..d833a0bce0 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -22,6 +22,9 @@ #include "careadlinkat.h" +#include "idx.h" +#include "minmax.h" + #include <errno.h> #include <limits.h> #include <string.h> @@ -65,11 +68,6 @@ readlink_stk (int fd, char const *filename, ssize_t (*preadlinkat) (int, char const *, char *, size_t), char stack_buf[STACK_BUF_SIZE]) { - char *buf; - size_t buf_size; - size_t buf_size_max = - SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; - if (! alloc) alloc = &stdlib_allocator; @@ -79,14 +77,14 @@ readlink_stk (int fd, char const *filename, buffer_size = STACK_BUF_SIZE; } - buf = buffer; - buf_size = buffer_size; + char *buf = buffer; + idx_t buf_size_max = MIN (IDX_MAX, MIN (SSIZE_MAX, SIZE_MAX)); + idx_t buf_size = MIN (buffer_size, buf_size_max); while (buf) { /* Attempt to read the link into the current buffer. */ - ssize_t link_length = preadlinkat (fd, filename, buf, buf_size); - size_t link_size; + idx_t link_length = preadlinkat (fd, filename, buf, buf_size); if (link_length < 0) { if (buf != buffer) @@ -98,7 +96,7 @@ readlink_stk (int fd, char const *filename, return NULL; } - link_size = link_length; + idx_t link_size = link_length; if (link_size < buf_size) { @@ -127,17 +125,13 @@ readlink_stk (int fd, char const *filename, if (buf != buffer) alloc->free (buf); - if (buf_size < buf_size_max / 2) - buf_size = 2 * buf_size + 1; - else if (buf_size < buf_size_max) - buf_size = buf_size_max; - else if (buf_size_max < SIZE_MAX) + if (buf_size_max / 2 <= buf_size) { errno = ENAMETOOLONG; return NULL; } - else - break; + + buf_size = 2 * buf_size + 1; buf = alloc->allocate (buf_size); } diff --git a/modules/careadlinkat b/modules/careadlinkat index 3f49aaecd7..b3375a9b20 100644 --- a/modules/careadlinkat +++ b/modules/careadlinkat @@ -7,6 +7,8 @@ lib/careadlinkat.h Depends-on: allocator +idx +minmax ssize_t unistd |