From: Paul Eggert Date: Thu, 20 Jun 2024 04:19:42 +0000 (-0400) Subject: sigsegv: avoid unlikely undefined behavior X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=459da066b3b4fce2dc6cdfa09840508d5de729d8;p=gnulib.git 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. --- diff --git a/ChangeLog b/ChangeLog index 1c156b791e..edbf067136 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2024-06-20 Paul Eggert + + 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 vasnprintf, u*-asnprintf tests: Add test of huge %ls arguments. diff --git a/lib/stackvma.c b/lib/stackvma.c index e93f939556..4424c6f58c 100644 --- a/lib/stackvma.c +++ b/lib/stackvma.c @@ -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