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

Xionghu Luo (luoxhu at gcc dot gnu.org) <yinyuefengyi at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yinyuefengyi at gmail dot com

--- Comment #4 from Xionghu Luo (luoxhu at gcc dot gnu.org) <yinyuefengyi at 
gmail dot com> ---
(In reply to liu zhenyu from comment #2)
> gcc/tree-ssa-strlen.cc, strlen_pass::handle_builtin_strlen (14.2 and trunk,
> :2330 on trunk), the branch where a strinfo already exists:
> 
>         if (!si->full_string_p && !si->stmt)
>           {
>             /* Until now we only had a lower bound on the string length.
>                Install LHS as the actual length.  */
>             si = unshare_strinfo (si);
>             tree old = si->nonzero_chars;
>             si->nonzero_chars = lhs;
>             si->full_string_p = true;
> 
> After memcpy (b, "abc", 3) the strinfo for b only has the lower bound 3. For
> strnlen, LHS is min (strlen (b), bound), not the length, but it is installed
> as the full length anyway. The path below (:2367), used when there is no
> strinfo yet, already has an if (!bound) check ("Only store the new length
> information for calls to strlen(), not for those to strnlen()"), added for
> PR86204 (r262114). This branch needs the same check (or should only install
> LHS when it is known to be smaller than the bound).
> 
> A second, builtins-only testcase fails the same way:
> 
> 
> __attribute__((noipa)) unsigned long f (void)
> {
>   char b[16];
>   __builtin_memcpy (b, "0123456789", 11);
>   __builtin_memcpy (b, "abc", 3);
>   unsigned long n = __builtin_strnlen (b, 5);
>   return n * 100 + __builtin_strlen (b);
> }
> int main (void) { if (f () != 510) __builtin_abort (); return 0; }

Could be fixed by:

diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc
index 8e2550f553a..60c4e5cccab 100644
--- a/gcc/tree-ssa-strlen.cc
+++ b/gcc/tree-ssa-strlen.cc
@@ -2327,7 +2327,11 @@ strlen_pass::handle_builtin_strlen ()
       strinfo *si = get_strinfo (idx);
       if (si != NULL)
        {
-         if (!si->full_string_p && !si->stmt)
+         /* For strnlen LHS is min (strlen (src), bound) rather than the
+            length of the string, so it must not be installed as the full
+            length; see the !bound guard on the new_strinfo path below
+            (PR86204) and, for the same reason, keep the lower bound.  */
+         if (!si->full_string_p && !si->stmt && !bound)
            {
              /* Until now we only had a lower bound on the string length.
                 Install LHS as the actual length.  */

Reply via email to