Yet another question regarding strncpy warning.
Here's the code:
#include <cstring>
extern char g_dest[16];
extern char g_src[16];
char* mycopy()
{
char * x = strncpy ( g_dest, g_src, sizeof ( g_dest ) - 1 );
return x;
}
Compile it with g++ version 8.3:
$ g++ --version
g++ (GCC) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ g++ -Wall -Wextra -Werror -O3 -c strncpy-warning2.cxx
strncpy-warning2.cxx: In function ‘char* mycopy()’:
strncpy-warning2.cxx:8:24: error: ‘char* strncpy(char*, const char*, size_t)’ output may be truncated copying 15 bytes from a string of length 15 [-Werror=stringop-truncation]
char * x = strncpy ( g_dest, g_src, sizeof ( g_dest ) - 1 );
~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
The warning can be worked around by either:
- making the g_src shorter than g_dest:
$ cat strncpy-warning2.cxx
#include <cstring>
extern char g_dest[16];
extern char g_src[15];
char* mycopy()
{
char * x = strncpy ( g_dest, g_src, sizeof ( g_dest ) - 1 );
return x;
}
$ g++ -Wall -Wextra -Werror -O3 -c strncpy-warning2.cxx
$
- Or explicitly adding a NUL terminator at the end of
g_dest:
$ cat strncpy-warning2.cxx
#include <cstring>
extern char g_dest[16];
extern char g_src[16];
char* mycopy()
{
char * x = strncpy ( g_dest, g_src, sizeof ( g_dest ) - 1 );
g_dest[ sizeof( g_dest ) - 1 ] = '\0';
return x;
}
$ g++ -Wall -Wextra -Werror -O3 -c strncpy-warning2.cxx
$
- Or if I make the g_src a pointer instead of an array:
$ cat strncpy-warning2.cxx
#include <cstring>
extern char g_dest[16];
extern char* g_src2;
char* mycopy()
{
char * x = strncpy ( g_dest, g_src2, sizeof ( g_dest ) - 1 );
return x;
}
$ g++ -Wall -Wextra -Werror -O3 -c strncpy-warning2.cxx
$
I understand that GCC is trying to warn against potential bugs on strncpy usage, however, I don't understand why we cannot do strncpy on 2 arrays of the same size? And why the warning message is saying the output maybe truncated ? ( i.e. I cannot find an example that the output can possibly be truncated unless GCC assumes g_src may not necessarily a valid NUL-terminated c-string. )
By googling, I see a similar case reported in GCC bugzilla: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87028, however, I'm not sure if that is the same case since that is marked as FIXED in the end but apparently my issue is still there in GCC 10.2.
Thank you!