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