]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
careadlinkat: avoid ptrdiff_t overflow
authorPaul Eggert <eggert@cs.ucla.edu>
Wed, 21 Apr 2021 18:03:39 +0000 (11:03 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Wed, 21 Apr 2021 18:10:48 +0000 (11:10 -0700)
* 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.

ChangeLog
lib/careadlinkat.c
modules/careadlinkat

index 3aaee32bff8c04e708b817b95b517e801c67131e..1e6cbd07f27a37dbf5ef65253faad833e0a355e9 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 18cfc114b69e98b5b97934294b91e44c642b01d2..d833a0bce005f03ec52cd696f8b4603a51120031 100644 (file)
@@ -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);
     }
 
index 3f49aaecd79773429d00741fb625f77bca38479f..b3375a9b20eb2aa76b81315ae61403cff9edf6ce 100644 (file)
@@ -7,6 +7,8 @@ lib/careadlinkat.h
 
 Depends-on:
 allocator
+idx
+minmax
 ssize_t
 unistd