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.

Reply via email to