C standard library has strncpy
function, declared as:
char *strncpy(char *dest, const char *src, size_t n);
It's a strange beast, as it fills n
bytes of memory pointed to by dest
. It does this by first copying from string src
as much as it can (either n
bytes copied or end of src
reached), then if n
bytes isn't full yet, it fills the rest with 0 bytes.
So, it wipes the entire dest
overwriting any old data or uninitialized garbage there. Also, it does not necessarily produce a string in dest
, because if strlen(src)
is equal or longer than n
, no terminating 0 byte is written. So, for copying NUL-terminated strings, it often does extra work with the 0 padding, unlike other string functions. And then it requires extra code to ensure result is a string (such as strncpy(dst, src, 10); dst[10]=0;
). So it looks as if it was not designed for simply copying C strings at all.
What was the original purpose of strncpy
function? Why does work the way it does?
I have two speculations, which I'll list here just as an example of what kind of confirmed answer I'm hoping to get:
- Maybe some earlier language back then had diffrent kind of strings (such as with length prefix), and for them
strncpy
worked somehow more logically as a string copy. Then Maybe C copied the function without altering behavior to account for terminating NUL. - Maybe at that time, before appearance of all the modern database alternatives, it was common to have binary data files with fixed size records, where C structs were accessed with
fseek
, followed byfwrite
/fread
. When setting fixed size string in such a struct, you'd want any garbage overwritten with 0, and you wouldn't want to waste precious storage space by always having one extra zero.
I don't know where an answer could be found, but perhaps some old reference manuals or textbooks from 1960's or 1970's might discuss the intended use.
strncpy
does overstrcpy
is great. To not do so would be a "short write vulnerability" See developer.apple.com/library/archive/documentation/Security/… for detailsstrncopy
is to convert from a C-style string to a fixed-length record. In other words: the fact that the result isn't a C-style string is the whole point of this function in the first place. The same reason applies to your second criticism: if you convert a C-style string contain UTF-8 to a fixed-length record, there is no guarantee that the record boundary lines up with a character boundary (or a grapheme cluster boundary or a glyph boundary or any other kind of text boundary). Besides,strncopy
predates UTF-8 by well over a decade, so makingstrncopy
aware