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:
$ 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
$
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
$
$ 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!
The best (most efficient, simplest, easiest to understand for both success and error cases) is to use memcpy when your source and destination are the same fairly small size. GCC won't warn you about that.
If you simply want GCC to not complain about your strncpy() call even if it is unsafe, you can enclose it in parentheses like this:
char * x = (strncpy ( g_dest, g_src, sizeof ( g_dest ) - 1 ));
GCC understands this to mean "I know what I'm doing, don't try to save me from myself."