Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does strncpy not null terminate?

Tags:

c

strncpy

strncpy() supposedly protects from buffer overflows. But if it prevents an overflow without null terminating, in all likelihood a subsequent string operation is going to overflow. So to protect against this I find myself doing:

strncpy( dest, src, LEN ); dest[LEN - 1] = '\0'; 

man strncpy gives:

The strncpy() function is similar, except that not more than n bytes of src are copied. Thus, if there is no null byte among the first n bytes of src, the result will not be null-terminated.

Without null terminating something seemingly innocent like:

   printf( "FOO: %s\n", dest ); 

...could crash.


Are there better, safer alternatives to strncpy()?

like image 824
Timothy Pratley Avatar asked Sep 21 '09 10:09

Timothy Pratley


People also ask

Is strncpy null terminating?

Problem with strncpy(): If there is no null character among the first n character of src, the string placed in dest will not be null-terminated. So strncpy() does not guarantee that the destination string will be NULL terminated.

Does strcpy null terminate?

Description. The strcpy() function copies string2, including the ending null character, to the location that is specified by string1. The strcpy() function operates on null-ended strings. The string arguments to the function should contain a null character (\0) that marks the end of the string.

Does strncat null terminate?

It always null-terminate. The strncat function appends not more than n characters (a null character and characters that follow it are not appended) from the array pointed to by s2 to the end of the string pointed to by s1 . The initial character of s2 overwrites the null character at the end of s1 .

Does strcat null terminate?

The function strcat() does not allocate any storage. The caller must insure that the buffer pointed to by s1 is long enough for string s2 and its terminating null character.


2 Answers

strncpy() is not intended to be used as a safer strcpy(), it is supposed to be used to insert one string in the middle of another.

All those "safe" string handling functions such as snprintf() and vsnprintf() are fixes that have been added in later standards to mitigate buffer overflow exploits etc.

Wikipedia mentions strncat() as an alternative to writing your own safe strncpy():

*dst = '\0'; strncat(dst, src, LEN); 

EDIT

I missed that strncat() exceeds LEN characters when null terminating the string if it is longer or equal to LEN char's.

Anyway, the point of using strncat() instead of any homegrown solution such as memcpy(..., strlen(...))/whatever is that the implementation of strncat() might be target/platform optimized in the library.

Of course you need to check that dst holds at least the nullchar, so the correct use of strncat() would be something like:

if (LEN) {     *dst = '\0'; strncat(dst, src, LEN-1); } 

I also admit that strncpy() is not very useful for copying a substring into another string, if the src is shorter than n char's, the destination string will be truncated.

like image 166
Ernelli Avatar answered Sep 28 '22 07:09

Ernelli


Originally, the 7th Edition UNIX file system (see DIR(5)) had directory entries that limited file names to 14 bytes; each entry in a directory consisted of 2 bytes for the inode number plus 14 bytes for the name, null padded to 14 characters, but not necessarily null-terminated. It's my belief that strncpy() was designed to work with those directory structures - or, at least, it works perfectly for that structure.

Consider:

  • A 14 character file name was not null terminated.
  • If the name was shorter than 14 bytes, it was null padded to full length (14 bytes).

This is exactly what would be achieved by:

strncpy(inode->d_name, filename, 14); 

So, strncpy() was ideally fitted to its original niche application. It was only coincidentally about preventing overflows of null-terminated strings.

(Note that null padding up to the length 14 is not a serious overhead - if the length of the buffer is 4 KB and all you want is to safely copy 20 characters into it, then the extra 4075 nulls is serious overkill, and can easily lead to quadratic behaviour if you are repeatedly adding material to a long buffer.)

like image 33
Jonathan Leffler Avatar answered Sep 28 '22 09:09

Jonathan Leffler