Warning: Non-standard function!
Syntax:
#include <string.h> // On BSD or compatible systems size_t strlcpy( char *dst, const char *src, size_t siz);
An attempt of the BSD people to “fix” strncpy. There is a reason this function is not in any ISO standard. See explanation after the description.
Original description:
Copy src
to string dst
of size siz
.
At most siz-1
characters will be copied.
Always NUL
terminates (unless siz == 0
).
Returns strlen(src);
if retval >= siz
, truncation occurred.
Why strlcpy is not an improvement, but rather a different, and quite possibly worse compromise:
Perceived advantages of strlcpy are:
NUL
terminated
The first “advantage” is supposed to make programs more robust by ensuring that the resulting strings are always NUL
terminated. First of all, they aren't, because the size argument can be 0
, in which case the code cannot write the terminating NUL
character. This fact is already a hint that strlcpy is not a very well designed function. Even if we ignore that flaw for a moment, there is more to it.
The good and warm feeling of security that strlcpy
may give its user is actually nothing more, than hiding an error. And hiding an error is never a good idea. strncpy has a very blunt and effective way of reporting if the copy operation failed: it does not NUL
terminate its target string. This means, that 2 hours after the strncpy call that went unchecked (without error handling), it is still clearly visible (in memory) what has happened. Our buffer has no terminating zero character. However 2 hours after strlcpy(buf,”assume”,3);
nothing whatsoever will show that the copy has failed, and the call went unchecked. In the lucky case, it will just result in overwriting some files or some mysteriously failed operations. In the very lucky case it will result in immediate damage. For example the overwritten files are important, and so the unchecked return value results in a crash or other system failure later on. Why is this luckier? Because we know there is a bug, even though strlcpy
has tried its best to hide it.
Not much different from strncpy you might say. You do not check the return value, you get problems. Except that with strncpy a look at the dump will tell you exactly what the problem is. No NUL
termination. With strlcpy
all you see is a C-string, with no indication that it has been truncated.
The second “advantage” seems to be more straightforward. If I copy 5 bytes into a 42K buffer, strncpy will write nearly 42K for no reason whatsoever, because we are only possibly interested in the NUL
after the 5 characters and the NUL
at the end of the buffer. That may be a performance hit you do not want to pay. If you meet such a rare situation while coding ask yourself: what is the maximum size for what I am copying? Is this the only thing that may go into that large buffer? It may well turn out that instead of 42*1024, you actually need 255 bytes max. for that filename you are copying. Depending on your situation, zeroing out a few bytes more might as well worth the trouble: you can use an ISO standard function.
So while there are corner cases when strlcpy
may actually be a lot faster than strncpy, it is also true the other way around. The designers of strlcpy
have made the unfortunate decision of ignoring the golden rule of: do one thing (and do that well). strlcpy
does not report only whether or not the copy was successful. Nope. It reports also the size of the input. Who asked for that? This means, that if our hypothetical situation above is reversed, strlcpy
will read 42K characters to find the length of the input, while it had only 5 bytes it could write. The caller may not even be interested in the length of the input. The caller just wants to give an error message saying “The filename is too long”. A malicious entity figures this out and may just start sending large strings and slow down a server tenfold.
So even the second, not-so-controversial “benefit” of strlcpy
over strncpy is questionable at best, and bogus at worse.
Why strlcpy is actually well-designed.
The above rant is misguided at best, a troll at worst.
The reason strlcpy returns the number of bytes written is so that you can check for short counts. This is the “error handling” that you are ranting about. Also, if you think that not NULL-terminating a string is an acceptable mechanism of error handling, then you're pretty far gone.
Another anonymous opinion: The rant is really silly. Please read the original paper: http://www.gratisoft.us/todd/papers/strlcpy.html