Subject: grep not building for me with gcc 11.2
From: Duncan Roe <[email-masked]>
To: [email-masked]
Cc: [email-masked], Duncan Roe <[email-masked]>
Date: Sat, 30 Oct 2021 19:40:25 +1100
List-Id: <debbugs-submit.debbugs.gnu.org>

Straight away let me say I have gotten around this and can now build grep. But
it toook me 2 days.

The actual bug is that `CFLAGS=` causes configure to enable gcc warnings. I
would then get multiline warnings like the one at end of this report. Because of
-Werror, the build would then stop.

I had been running configure as `CFLAGS='-g3 -ggdb' ./configure --disable-nls`.
Eventually I tried plain `./configure` which built. Tests revealed simply
`CFLAGS=-g ./configure` provokes the warnings. Now I run `CFLAGS='-g3 -ggdb'
./configure --disable-gcc-warnings --disable-nls`.

To stop other folks running into this, configure.ac needs to be fixed to not
--enable-gcc-warnings of its own accord.

Cheers ... Duncan.

========================================

All the "error" lines flagged by gcc11.2 are false alarms. This is a list of
them:
> exclude.c:691:10: error: leak of FILE 'in' [CWE-775] [-Werror=analyzer-file-leak]
> fts.c:1497:25: error: use of NULL 'cp' where non-null expected [CWE-476] [-Werror=analyzer-null-argument]
> regex_internal.c:992:17: error: dereference of possibly-NULL 'next_nodes.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:992:17: error: dereference of possibly-NULL '*dests_node.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:992:17: error: dereference of possibly-NULL 'union_set.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:992:17: error: dereference of possibly-NULL '*set.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:992:17: error: dereference of possibly-NULL '*set.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:992:17: error: dereference of possibly-NULL 'new_nodes.elems' [CWE-690] [-Werror=analyzer-possible-null-dereference]
> regex_internal.c:1040:7: error: use of possibly-NULL 'next_nodes.elems' where non-null expected [CWE-690] [-Werror=analyzer-possible-null-argument]
> regex_internal.c:1040:7: error: use of possibly-NULL '*dest.elems' where non-null expected [CWE-690] [-Werror=analyzer-possible-null-argument]

These are all in gnulib. The following patch eliminates all of them, but don't
apply it. The patch is to highlight code constructs that gcc can't analyse
adequately.

Should I report these to the gcc team? They tend to like simple sources with no
headers and so on - I don't know if I can find the time to do that. But maybe I
could do 1 or 2. At least it's their own source (gnu's, not gcc's).

========================================

Here's an analysis of the first alleged error. add_exclude_file() is a short
function:
> int
> add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
>                   struct exclude *ex, char const *file_name, int options,
>                   char line_end)
> {
>   bool use_stdin = file_name[0] == '-' && !file_name[1];
>   FILE *in;
>   int rc = 0;
>
>   if (use_stdin)
>     in = stdin;
>   else if (! (in = fopen (file_name, "re")))
>     return -1;
>
>   rc = add_exclude_fp (call_addfn, ex, in, options, line_end, &add_func);
>
>   if (!use_stdin && fclose (in) != 0)
>     rc = -1;
>
>   return rc;
> }
If `use_stdin` is false then `in` becomes the fd of some file. But if
`use_stdin` is false, then `in` is rigorously closed. So there can be no file
leak.

> In function 'add_exclude_file':
> exclude.c:691:10: error: leak of FILE 'in' [CWE-775] [-Werror=analyzer-file-leak]
>   691 |   return rc;
>       |          ^~
>   'add_exclude_file': events 1-8
>     |
>     |  673 | add_exclude_file (void (*add_func) (struct exclude *, char const *, int),
>     |      | ^~~~~~~~~~~~~~~~
>     |      | |
>     |      | (1) entry to 'add_exclude_file'
>     |......
>     |  681 |   if (use_stdin)
>     |      |      ~
>     |      |      |
>     |      |      (2) following 'false' branch (when 'use_stdin == 0')...
>     |  682 |     in = stdin;
>     |  683 |   else if (! (in = fopen (file_name, "re")))
>     |      |           ~        ~~~~~~~~~~~~~~~~~~~~~~~
>     |      |           |        |
>     |      |           |        (3) ...to here
>     |      |           |        (4) opened here
>     |      |           (5) assuming 'in' is non-NULL
>     |      |           (6) following 'false' branch (when 'in' is non-NULL)...
>     |......
>     |  686 |   rc = add_exclude_fp (call_addfn, ex, in, options, line_end, &add_func);
>     |      |        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     |      |        |
>     |      |        (7) ...to here
>     |      |        (8) calling 'add_exclude_fp' from 'add_exclude_file'
>     |
>     +--'add_exclude_fp': event 9
>            |
>            |  608 | add_exclude_fp (void (*add_func) (struct exclude *, char const *, int, void *),
>            |      | ^~~~~~~~~~~~~~
>            |      | |
>            |      | (9) entry to 'add_exclude_fp'
>            |
>          'add_exclude_fp': events 10-16
>            |
>            |  622 |   while ((c = getc (fp)) != EOF)
>            |      |                          ^
>            |      |                          |
>            |      |                          (10) following 'false' branch (when 'c == -1')...
>            |......
>            |  629 |   if (ferror (fp))
>            |      |       ~~~~~~~~~~~
>            |      |       |
>            |      |       (11) ...to here
>            |......
>            |  634 |   lim = buf + buf_count + ! (buf_count == 0 || buf[buf_count - 1] == line_end);
>            |      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>            |      |                           |
>            |      |                           (12) following 'false' branch (when 'buf_count == 0')...
>            |      |                           (13) ...to here
>            |......
>            |  640 |   for (p = buf; p < lim; p++)
>            |      |                 ~~~~~~~
>            |      |                   |
>            |      |                   (16) following 'false' branch (when 'p >= lim')...
>            |  641 |     if (*p == line_end)
>            |      |        ~
>            |      |        |
>            |      |        (14) following 'true' branch...
>            |  642 |       {
>            |  643 |         char *pattern_end = p;
>            |      |               ~~~~~~~~~~~
>            |      |               |
>            |      |               (15) ...to here
>            |
>          'add_exclude_fp': event 17
>            |
>            |  661 |   errno = e;
>            |      |   ^~~~~
>            |      |   |
>            |      |   (17) ...to here
>            |
>     <------+
>     |
>   'add_exclude_file': events 18-21
>     |
>     |  686 |   rc = add_exclude_fp (call_addfn, ex, in, options, line_end, &add_func);
>     |      |        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     |      |        |
>     |      |        (18) returning to 'add_exclude_file' from 'add_exclude_fp'
>     |  687 |
>     |  688 |   if (!use_stdin && fclose (in) != 0)
>     |      |      ~
>     |      |      |
>     |      |      (19) following 'false' branch...
>     |......
>     |  691 |   return rc;
>     |      |          ~~
>     |      |          |
>     |      |          (20) ...to here
>     |      |          (21) 'in' leaks here; was opened at (4)
>     |
> 13:51:11$ gcc --version
> gcc (GCC) 11.2.0

Duncan Roe (1):
  Silly patch to avoid some gcc 11.2 warnings

 lib/exclude.c        | 9 +++++++--
 lib/fts.c            | 2 +-
 lib/regex_internal.c | 6 +++---
 3 files changed, 11 insertions(+), 6 deletions(-)

-- 
2.33.1