https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128131
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |wrong-code
Summary|__builtin_object_size of |[13/14/15/16/17
|strndup result is too |Regression]__builtin_object
|small, valid code aborts |_size of strndup result is
|with _FORTIFY_SOURCE |too small, valid code
| |aborts with _FORTIFY_SOURCE
Known to work| |12.2.0
Known to fail| |13.1.0, 13.4.0, 14.2.0,
| |15.3.0, 16.2.0, 17.0
--- Comment #1 from liu zhenyu <lzy20000419 at outlook dot com> ---
Root cause is in strdup_object_size, which was added in GCC 13 by e5cfb9cac1
("tree-object-size: Support strndup and strdup").
gcc/tree-object-size.cc, 14.2 :826-880, trunk :978-1032:
```
if (is_strndup)
n = fold_build2 (PLUS_EXPR, sizetype, size_one_node,
gimple_call_arg (call, 1));
...
/* For maximum estimate, our next best guess is the object size of the
source. */
if (size_unknown_p (sz, object_size_type)
&& !(object_size_type & OST_MINIMUM))
compute_builtin_object_size (src, object_size_type, &sz);
...
return n ? fold_build2 (MIN_EXPR, sizetype, n, sz) : sz;
```
There are two problems:
1. For strdup the NUL must be inside SRC, so the object size of SRC is a
correct cap. strndup can copy all of SRC and then add a NUL, so the cap has to
be objsize (src) + 1.
2. n + 1 is computed in sizetype, so it wraps to 0 when n == SIZE_MAX.
The MIN_EXPR then gives a maximum size that is too small, and FORTIFY aborts.
Suggested fix: for strndup, add 1 to the objsize (src) fallback, and saturate
n, e.g. n = MAX_EXPR (n + 1, n). I tested this on 14.2: both testcases pass,
and the gcc.dg/builtin-*object-size*.c run tests give the same results as
before.