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. */