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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
   Last reconfirmed|                            |2018-05-14
                 CC|                            |msebor at gcc dot gnu.org
           Assignee|unassigned at gcc dot gnu.org      |msebor at gcc dot 
gnu.org
            Summary|[8/9 Regression] regression |-Wsizeof-pointer-memaccess
                   |with strncat and -Wall in   |for strncat with size of
                   |GCC 8                       |source
     Ever confirmed|0                           |1

--- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> ---
(The warning behaves as designed so this is not a regression.  I've changed the
Summary to reflect that.)

The code in the test case is correct and safe, and reflects one of the original
and intended uses of the function.  Unfortunately, due to a poor understanding
of the various string functions[1], many calls to strncat() with either the
size of the source or (to a lesser extent) the size of the destination have
been mistakes that have led to either buffer overflow or inadvertent
truncation.  To avoid these mistakes the recommended way to call the function
is to pass it the amount of space remaining in the destination, e.g., like
so[2]:

  strncat (dst, src, dstsize - strlen (d) - 1);

The warning is designed to help detect these mistakes and encourage this idiom.

Ideally, the warning would detect the safe calls (like the one in the test
case) and avoid triggering for them, but it's not always possible.  In the test
case, it's impossible to detect the length of the destination string at the
point where GCC sees the use of 'sizeof source' in the strncat() call; at the
point where the length is known the fact that the bound is the result of
'sizeof source' has been lost.

Since in the test case strncat() is being used to constrain the copy to avoid
reading past the end of a non-string (i.e., an array of characters not
necessarily terminated by a NUL) I'll see if GCC can be taught to recognize the
attribute in this context to suppress the warning.  Until then (or if
annotating the member isn't an option), the warning can be suppressed either by
a #pragma GCC diagnostic, or by introducing a temporary pointer pointing to the
member array and passing the pointer to strncat, or by introducing a temporary
for the size of the source and passing it to the function as the bound:

  char* __attribute__ ((nonstring)) p = u.ut_user;
  enum { N = sizeof u.ut_user };
  strncat (buf, u.ut_user, N);

[1]
https://www.usenix.org/legacy/event/usenix99/full_papers/millert/millert.pdf
[2]
https://www.us-cert.gov/bsi/articles/knowledge/coding-practices/strncpy-and-strncat

Reply via email to