Hello,

Using GCC10 on Fedora 31, I built coreutils from a git clone of the latest
sources.
After running
$./bootstrap && ./configure && make
I got a few deprecation warnings for sys/sysctl.h which I skipped over, and
found an interesting error while building src/yes.o:
  CC       src/yes.o
src/yes.c: In function 'main':
src/yes.c:110:20: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]
  110 |   buf[bufused - 1] = '\n';
      |   ~~~~~~~~~~~~~~~~~^~~~~~
src/yes.c:100:51: note: at offset -1 to an object with size 8192 allocated
by 'xmalloc' here
  100 |   char *buf = reuse_operand_strings ? *operands : xmalloc
(bufalloc);
      |                                                   ^~~~~~~~~~~~~~~~~~

The compiler didn't deduce that the for loop will always iterate at least
once, therefore my first thought was to assert(operands < operand_lim)
before the start of the for loop on line 102.
I 'heard' :) about assure and decided to use that instead, before realizing
that I could make it obvious that the loop would run at least once by
converting the for loop into a do-while loop.
This avoided the warning. I also made sure the tests still pass on F31.

Chris Meyering
From 94b603963b93c2d5669d3053c8682b4d442c1a8d Mon Sep 17 00:00:00 2001
From: Chris Meyering <christophe.meyer...@gmail.com>
Date: Wed, 29 Jan 2020 22:34:48 -0800
Subject: [PATCH] yes: rearrange code to prevent gcc10 warning

* src/yes.c (main): Convert for loop to do-while in order to tell GCC10
that the loop will be run at least once.  This avoids the following:
src/yes.c:110:20: error: writing 1 byte into a region of size 0
---
 src/yes.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/yes.c b/src/yes.c
index e01213065..335a23b8f 100644
--- a/src/yes.c
+++ b/src/yes.c
@@ -99,7 +99,8 @@ main (int argc, char **argv)
      the operands strings; this wins when the buffer would be large.  */
   char *buf = reuse_operand_strings ? *operands : xmalloc (bufalloc);
   size_t bufused = 0;
-  for (char **operandp = operands; operandp < operand_lim; operandp++)
+  char **operandp = operands;
+  do
     {
       size_t operand_len = strlen (*operandp);
       if (! reuse_operand_strings)
@@ -107,6 +108,7 @@ main (int argc, char **argv)
       bufused += operand_len;
       buf[bufused++] = ' ';
     }
+  while (++operandp < operand_lim);
   buf[bufused - 1] = '\n';
 
   /* If a larger buffer was allocated, fill it by repeating the buffer
-- 
2.24.1

Reply via email to