https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128196
--- Comment #2 from liu zhenyu <lzy20000419 at outlook dot com> ---
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; }