public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "dmalcolm at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug analyzer/113606] New: -Wanalyzer-infinite-recursion false positive on code involving strstr, memset, strnlen and -D_FORTIFY_SOURCE
Date: Thu, 25 Jan 2024 22:44:17 +0000	[thread overview]
Message-ID: <bug-113606-4@http.gcc.gnu.org/bugzilla/> (raw)

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113606

            Bug ID: 113606
           Summary: -Wanalyzer-infinite-recursion false positive on code
                    involving strstr, memset, strnlen and
                    -D_FORTIFY_SOURCE
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: analyzer
          Assignee: dmalcolm at gcc dot gnu.org
          Reporter: dmalcolm at gcc dot gnu.org
  Target Milestone: ---

Taking the following from this downstream bug report:
  https://bugzilla.redhat.com/show_bug.cgi?id=2260398

Create str.c:
```
#define _POSIX_C_SOURCE 200809L
#include <stddef.h>
#include <stdio.h>
#include <string.h>

static char*
strredact(char *str, const char *sub, const char c)
{
  char *p;
  if (!str) return NULL;
  if (!sub) return str;
  p = strstr(str, sub);
  if (!c || !p) return str;
  (void)memset(p, c, strnlen(sub, strlen(str)));
  return strredact(str, sub, c);
}

int
main (void)
{
  char string[] = "This_is_a_string.";
  return printf("%s\n", strredact(string, "_", ' '));
}
```

Actual Results (with trunk aka gcc 14):  

$ gcc -fanalyzer -Werror -O str.c
$ gcc -fanalyzer -Werror -O -D_FORTIFY_SOURCE=2 str.c
str.c: In function ‘strredact’:
str.c:16:10: error: infinite recursion [CWE-674]
[-Werror=analyzer-infinite-recursion]
   16 |   return strredact(str, sub, c);
      |          ^~~~~~~~~~~~~~~~~~~~~~
  ‘strredact’: events 1-9
    |
    |    8 | strredact(char *str, const char *sub, const char c)
    |      | ^~~~~~~~~
    |      | |
    |      | (1) entry to ‘strredact’
    |......
    |   11 |   if (!str) return NULL;
    |      |      ~
    |      |      |
    |      |      (2) following ‘false’ branch (when ‘str’ is non-NULL)...
    |   12 |   if (!sub) return str;
    |      |      ~
    |      |      |
    |      |      (3) ...to here
    |      |      (4) following ‘false’ branch (when ‘sub’ is non-NULL)...
    |   13 |   p = strstr(str, sub);
    |      |       ~~~~~~~~~~~~~~~~
    |      |       |
    |      |       (5) ...to here
    |      |       (6) when ‘strstr’ returns non-NULL
    |   14 |   if (!c || !p) return str;
    |      |      ~
    |      |      |
    |      |      (7) following ‘false’ branch...
    |   15 |   (void)memset(p, c, strnlen(sub, strlen(str)));
    |      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    |      |         |
    |      |         (8) ...to here
    |   16 |   return strredact(str, sub, c);
    |      |          ~~~~~~~~~~~~~~~~~~~~~~
    |      |          |
    |      |          (9) calling ‘strredact’ from ‘strredact’
    |
    +--> ‘strredact’: events 10-18
           |
           |    8 | strredact(char *str, const char *sub, const char c)
           |      | ^~~~~~~~~
           |      | |
           |      | (10) initial entry to ‘strredact’
           |......
           |   11 |   if (!str) return NULL;
           |      |      ~
           |      |      |
           |      |      (11) following ‘false’ branch (when ‘str’ is
non-NULL)...
           |   12 |   if (!sub) return str;
           |      |      ~
           |      |      |
           |      |      (12) ...to here
           |      |      (13) following ‘false’ branch (when ‘sub’ is
non-NULL)...
           |   13 |   p = strstr(str, sub);
           |      |       ~~~~~~~~~~~~~~~~
           |      |       |
           |      |       (14) ...to here
           |      |       (15) when ‘strstr’ returns non-NULL
           |   14 |   if (!c || !p) return str;
           |      |      ~
           |      |      |
           |      |      (16) following ‘false’ branch...
           |   15 |   (void)memset(p, c, strnlen(sub, strlen(str)));
           |      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           |      |         |
           |      |         (17) ...to here
           |   16 |   return strredact(str, sub, c);
           |      |          ~~~~~~~~~~~~~~~~~~~~~~
           |      |          |
           |      |          (18) calling ‘strredact’ from ‘strredact’
           |
           +--> ‘strredact’: events 19-20
                  |
                  |    8 | strredact(char *str, const char *sub, const char c)
                  |      | ^~~~~~~~~
                  |      | |
                  |      | (19) recursive entry to ‘strredact’; previously
entered at (10)
                  |      | (20) apparently infinite recursion
                  |
cc1: all warnings being treated as errors



Expected Results:  
$ gcc -fanalyzer -Werror -O str.c
$ gcc -fanalyzer -Werror -O -D_FORTIFY_SOURCE=2 str.c

(no output)

Affects trunk.
Doesn't affect gcc 13.2

Reproduced on Godbolt, see https://godbolt.org/z/ebsq7WhxG
https://godbolt.org/z/Tn7oe1EbG - a slightly more minimized example

             reply	other threads:[~2024-01-25 22:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-25 22:44 dmalcolm at gcc dot gnu.org [this message]
2024-02-15 14:34 ` [Bug analyzer/113606] [14 Regression] " dmalcolm at gcc dot gnu.org
2024-03-04 13:08 ` rguenth at gcc dot gnu.org
2024-03-07 20:44 ` law at gcc dot gnu.org
2024-05-07  7:44 ` [Bug analyzer/113606] [14/15 " rguenth at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-113606-4@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).