On 12/14/22 23:45, Alejandro Colomar wrote: > Hi, > > I was rewriting the strncat(3) manual page, and when I tried to compile the > example program, I got a surprise from the compiler. > > Here goes the page: > > >   strncat(3)               Library Functions Manual              strncat(3) > >   NAME >          strncat  -  concatenate  a  null‐padded  character sequence into a >          string > >   LIBRARY >          Standard C library (libc, -lc) > >   SYNOPSIS >          #include > >          char *strncat(char *restrict dst, const char src[restrict .sz], >                         size_t sz); > >   DESCRIPTION >          This function catenates the input character sequence contained  in >          a  null‐padded  fixed‐width  buffer,  into  a string at the buffer >          pointed to by dst.  The programmer is responsible for allocating a >          buffer large enough, that is, strlen(dst) + strnlen(src, sz) + 1. > >          An implementation of this function might be: > >              char * >              strncat(char *restrict dst, const char *restrict src, size_t sz) >              { >                  int   len; >                  char  *end; > >                  len = strnlen(src, sz); >                  end = dst + strlen(dst); >                  end = mempcpy(end, src, len); >                  *end = '\0'; > >                  return dst; >              } > >   RETURN VALUE >          strncat() returns dest. > >   ATTRIBUTES >          [...] > >   STANDARDS >          POSIX.1‐2001, POSIX.1‐2008, C89, C99, SVr4, 4.3BSD. > >   CAVEATS >          The  name of this function is confusing.  This function has no re‐ >          lation with strncpy(3). > >          If the destination buffer is not large enough, the behavior is un‐ >          defined.  See _FORTIFY_SOURCE in feature_test_macros(7). > >   BUGS >          This function  can  be  very  inefficient.   Read  about  Shlemiel >          the       painter      ⟨https://www.joelonsoftware.com/2001/12/11/ >          back-to-basics/⟩. > >   EXAMPLES >          #include >          #include >          #include > >          int >          main(void) >          { >              char    buf[BUFSIZ]; >              size_t  len; > >              buf[0] = '\0';  // There’s no ’cpy’ function to this ’cat’. >              strncat(buf, "Hello ", 6); >              strncat(buf, "world", 42);  // Padding null bytes ignored. >              strncat(buf, "!", 1); >              len = strlen(buf); >              printf("[len = %zu]: <%s>\n", len, buf); > >              exit(EXIT_SUCCESS); >          } > >   SEE ALSO >          string(3), string_copy(3) > >   Linux man‐pages (unreleased)      (date)                       strncat(3) > > > And when you compile that, you get: > > $ cc -Wall -Wextra ./strncat.c > ./strncat.c: In function ‘main’: > ./strncat.c:12:12: warning: ‘strncat’ specified bound 6 equals source length > [-Wstringop-overflow=] >    12 |            strncat(buf, "Hello ", 6); >       |            ^~~~~~~~~~~~~~~~~~~~~~~~~ > ./strncat.c:14:12: warning: ‘strncat’ specified bound 1 equals source length > [-Wstringop-overflow=] >    14 |            strncat(buf, "!", 1); >       |            ^~~~~~~~~~~~~~~~~~~~ > > > So, what?  Where's the problem?  This function does exactly that: "take an > unterminated character sequence and catenate it to an existing string".  Clang > seems to be fine with the code. Maybe it's saying that I should be using strncat(buf, "!"); because the length is useless? > > Cheers, > > Alex > > --