From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 23F3F3858D28; Thu, 25 Jan 2024 22:44:20 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 23F3F3858D28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1706222660; bh=1JFzqG94SZTHyhGNS5dPRt12AC79kfQoj1sBkyLyLpo=; h=From:To:Subject:Date:From; b=QK2KB60w/ofFUxAPqUnTkOzixOklXl5U6/wnLsZm8FwCeX/M5AqbvqazpVUstgrOL NN2VUPL0mBIkALOoOi9Yyez82XEd5BVtV3kyjpC3htmmJ/N17dzyrPSqEgwRO0McK8 hppXwqZsA/ohQEpx5+xeKZkgJL+8lVRTjWT7GEPs= From: "dmalcolm at gcc dot 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 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: analyzer X-Bugzilla-Version: 14.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: dmalcolm at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: dmalcolm at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D113606 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=3D2260398 Create str.c: ``` #define _POSIX_C_SOURCE 200809L #include #include #include static char* strredact(char *str, const char *sub, const char c) { char *p; if (!str) return NULL; if (!sub) return str; p =3D 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[] =3D "This_is_a_string."; return printf("%s\n", strredact(string, "_", ' ')); } ``` Actual Results (with trunk aka gcc 14):=20=20 $ gcc -fanalyzer -Werror -O str.c $ gcc -fanalyzer -Werror -O -D_FORTIFY_SOURCE=3D2 str.c str.c: In function =E2=80=98strredact=E2=80=99: str.c:16:10: error: infinite recursion [CWE-674] [-Werror=3Danalyzer-infinite-recursion] 16 | return strredact(str, sub, c); | ^~~~~~~~~~~~~~~~~~~~~~ =E2=80=98strredact=E2=80=99: events 1-9 | | 8 | strredact(char *str, const char *sub, const char c) | | ^~~~~~~~~ | | | | | (1) entry to =E2=80=98strredact=E2=80=99 |...... | 11 | if (!str) return NULL; | | ~ | | | | | (2) following =E2=80=98false=E2=80=99 branch (when =E2=80= =98str=E2=80=99 is non-NULL)... | 12 | if (!sub) return str; | | ~ | | | | | (3) ...to here | | (4) following =E2=80=98false=E2=80=99 branch (when =E2=80= =98sub=E2=80=99 is non-NULL)... | 13 | p =3D strstr(str, sub); | | ~~~~~~~~~~~~~~~~ | | | | | (5) ...to here | | (6) when =E2=80=98strstr=E2=80=99 returns non-NULL | 14 | if (!c || !p) return str; | | ~ | | | | | (7) following =E2=80=98false=E2=80=99 branch... | 15 | (void)memset(p, c, strnlen(sub, strlen(str))); | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (8) ...to here | 16 | return strredact(str, sub, c); | | ~~~~~~~~~~~~~~~~~~~~~~ | | | | | (9) calling =E2=80=98strredact=E2=80=99 from =E2=80= =98strredact=E2=80=99 | +--> =E2=80=98strredact=E2=80=99: events 10-18 | | 8 | strredact(char *str, const char *sub, const char c) | | ^~~~~~~~~ | | | | | (10) initial entry to =E2=80=98strredact=E2=80=99 |...... | 11 | if (!str) return NULL; | | ~ | | | | | (11) following =E2=80=98false=E2=80=99 branch (whe= n =E2=80=98str=E2=80=99 is non-NULL)... | 12 | if (!sub) return str; | | ~ | | | | | (12) ...to here | | (13) following =E2=80=98false=E2=80=99 branch (whe= n =E2=80=98sub=E2=80=99 is non-NULL)... | 13 | p =3D strstr(str, sub); | | ~~~~~~~~~~~~~~~~ | | | | | (14) ...to here | | (15) when =E2=80=98strstr=E2=80=99 returns non-NU= LL | 14 | if (!c || !p) return str; | | ~ | | | | | (16) following =E2=80=98false=E2=80=99 branch... | 15 | (void)memset(p, c, strnlen(sub, strlen(str))); | | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | | | (17) ...to here | 16 | return strredact(str, sub, c); | | ~~~~~~~~~~~~~~~~~~~~~~ | | | | | (18) calling =E2=80=98strredact=E2=80=99 from = =E2=80=98strredact=E2=80=99 | +--> =E2=80=98strredact=E2=80=99: events 19-20 | | 8 | strredact(char *str, const char *sub, const char= c) | | ^~~~~~~~~ | | | | | (19) recursive entry to =E2=80=98strredact=E2=80= =99; previously entered at (10) | | (20) apparently infinite recursion | cc1: all warnings being treated as errors Expected Results:=20=20 $ gcc -fanalyzer -Werror -O str.c $ gcc -fanalyzer -Werror -O -D_FORTIFY_SOURCE=3D2 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=