The semantics of strlcpy and strlcat

Paul Eggert eggert@cs.ucla.edu
Fri Jan 22 00:29:00 GMT 2016


On 01/21/2016 03:37 PM, Zack Weinberg wrote:
> * If the buffers overlap, the behavior is undefined.  That is, either
> memcpy is used, or an overlap-blind copy loop is used - either way,
> the "correct" behavior (= "what memmove would have done") will not
> always happen.

But the OpenBSD implementation's behavior is not undefined. True, 
OpenBSD strlcpy doesn't behave the way memmove would, but the behavior 
of its overlap-blind copy is well-defined on all platforms. Similarly 
for NetBSD and FreeBSD; they all use the same overlap-blind copy.

We cannot assume that overlap-blind copying is "incorrect" and that 
memmove semantics are "correct" when we are trying to figure out what 
the correct behavior should be, as that would be begging the question.

> * If the destination-size argument is zero, the destination-buffer
> pointer is not dereferenced. This is not by accident - all
> implementations take special care to do this.

The implementations you looked at may do that, but the NetBSD 
implementation doesn't. NetBSD strlcpy does not allow a size-zero 
destination if the destination pointer is null. See:

http://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/common/lib/libc/string/strlcpy.c

NetBSD demonstrates that there's no need to support calls that specify 
the null pointer and size zero.

> * Three out of four strlcat implementations have well-defined behavior
> (they return `destsize+strlen(src)` and leave the destination buffer
> unchanged) when the destination buffer does not contain a terminating
> nul.  The other one blindly calls strlen() on the destination buffer,
> and I very strongly suspect that this is an oversight.

You missed an oversight in the other three implementations: adding 
destsize to strlen(src) can overflow when the destination buffer does 
not contain a terminating NUL. This can cause strlcat to return a 
numerically incorrect value, which could cause a caller to incorrectly 
conclude that the result fits within the output buffer, leading to havoc.

It is this sort of thing that caused us to go to a more-conservative 
spec, which says that the troublesome cases noted above have undefined 
behavior.



More information about the Libc-alpha mailing list