The problem of strncpy and the solution of GCC compile time checking

There is a problem with strcpy(), but there is still a problem with strncpy().

#define PATH_MAX 128

e.g. strncpy(file_path, src, PATH_MAX);

Strncpy () is prone to two problems: 1) the source string is too long, resulting in no terminator, and there are out of bounds garbled references. 2) the length of string is easily inconsistent with the nominal length. Like file_ Path says that it can support 128 characters at most. However, if the terminator is included, it is usually only 127.

Strncpy source code: when SRC reaches count, there is no terminator:

char* strncpy(char* dest, const char* source, size_t count)
{
	char* start=dest;
	while (count && (*dest++=*source++))
		count--;
	if(count)
		while (--count)
			*dest++='\0';
	return(start);
}

A good solution is:

1. Ensure that the length of the string is the nominal length, not the virtual mark

2. Secondly, it is not allowed to cross the boundary. It must have the correct ending character ‘\ 0’

3. The length of DST must be at least one character longer than Src

The possible implementation is as follows: using safe_ Strncpy (), and get DST length for security check

#define PATH_MAX 128
char file_path[PATH_MAX+1];

e.g. safe_strncpy(file_path, src,PATH_MAX+1, PATH_MAX);
int safe_strncpy(char *dst, const char *src, size_t dst_size,size_t str_size)
{
    if(dst_size <= str_size)
        return -1;
    dst[dst_size-1] = '\0';
    return strncpy(dst,src,str_size);
}

The key is to make sure that the DST string is long enough.

It’s not very good to check at run time. The reason is that you have to test it before you can find the problem.

A better solution is to check the DST length during compilation.

GCC compile time checking scheme

GCC seems to have started to support compile time assertions in 4.3

_ Static_ assert( expr,”msg”)

If the code is wrongly written and the DST space is equal to size, there is no terminator bug and an error should be reported.

The following font string file_ Path supports 128 characters, but file does not_ The path definition space is also 128, which should be defined as 129

#define PATH_MAX 128
char file_path[PATH_MAX];

e.g. safe_strncpy(file_path, src, PATH_MAX);

The results are as follows

../include/comm.h:202:5: error: static assertion failed: "strncp small buf size error"
     _Static_assert( sizeof(dst) > size,"strncp small buf size error");\
     ^
cmd_mark.c:137:13: note: in expansion of macro ‘safe_strncpy’
             safe_strncpy(file_path, optarg, OS_PATH_MAX);

The code is as follows:

#define safe_strncpy(dst,src,size)  \
do { \
    _Static_assert( sizeof(dst) > size,"strncp small buf size error");\
   _safe_strncpy(dst,src,sizeof(dst),size); \
        }while(0)

In this way, all calls to safe can be guaranteed as long as they are compiled_ There’s enough space for strncpy().

The power of compile time assertions lies in finding problems earlier than at run time. If someone misuses safe_ Strncpy (char * PTR, SRC, size) also finds problems in code ahead of time, rather than at run time or even after release.


Read More: