]> Savannah Git Hosting - gnulib.git/commitdiff
sigsegv: avoid unlikely undefined behavior
authorPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Jun 2024 04:19:42 +0000 (00:19 -0400)
committerPaul Eggert <eggert@cs.ucla.edu>
Thu, 20 Jun 2024 04:20:54 +0000 (00:20 -0400)
Problem found by Coverity for diffutils and reported by Wasser Mai in:
https://bugs.gnu.org/71535
* lib/stackvma.c (rof_open) [__linux__ || __FreeBSD__ || etc]:
Don’t assume result of ‘read’ fits in int.
Avoid undefined behavior if ‘n + MIN_LEFTOVER’ would overflow.
Also, move a test to be after an (n == 0) test, to help the compiler.

ChangeLog
lib/stackvma.c

index 1c156b791ec47362b85a2270375b8d704bd2bee9..edbf067136d40bf676157f6e79316573e12ce02d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2024-06-20  Paul Eggert  <eggert@re>
+
+       sigsegv: avoid unlikely undefined behavior
+       Problem found by Coverity for diffutils and reported by Wasser Mai in:
+       https://bugs.gnu.org/71535
+       * lib/stackvma.c (rof_open) [__linux__ || __FreeBSD__ || etc]:
+       Don’t assume result of ‘read’ fits in int.
+       Avoid undefined behavior if ‘n + MIN_LEFTOVER’ would overflow.
+       Also, move a test to be after an (n == 0) test, to help the compiler.
+
 2024-06-19  Bruno Haible  <bruno@clisp.org>
 
        vasnprintf, u*-asnprintf tests: Add test of huge %ls arguments.
index e93f939556a6154c268a962819de8d5ab9ddfb2a..4424c6f58c61c09145acc7ec7f9aafd63d5fe837 100644 (file)
@@ -176,7 +176,7 @@ rof_open (struct rofile *rof, const char *filename)
       /* Attempt to read the contents in a single system call.  */
       if (size > MIN_LEFTOVER)
         {
-          int n = read (fd, rof->buffer, size);
+          ssize_t n = read (fd, rof->buffer, size);
           if (n < 0 && errno == EINTR)
             goto retry;
 # if defined __DragonFly__
@@ -186,7 +186,7 @@ rof_open (struct rofile *rof, const char *filename)
               if (n <= 0)
                 /* Empty file.  */
                 goto fail1;
-              if (n + MIN_LEFTOVER <= size)
+              if (MIN_LEFTOVER <= size - n)
                 {
                   /* The buffer was sufficiently large.  */
                   rof->filled = n;
@@ -201,15 +201,15 @@ rof_open (struct rofile *rof, const char *filename)
                       if (n < 0)
                         /* Some error.  */
                         goto fail1;
-                      if (n + MIN_LEFTOVER > size - rof->filled)
-                        /* Allocate a larger buffer.  */
-                        break;
                       if (n == 0)
                         {
                           /* Reached the end of file.  */
                           close (fd);
                           return 0;
                         }
+                      if (size - rof->filled - n < MIN_LEFTOVER)
+                        /* Allocate a larger buffer.  */
+                        break;
                       rof->filled += n;
                     }
 # else