[PATCH v7] Implement strlcpy, strlcat [BZ #178]

Alexander Cherepanov ch3root@openwall.com
Tue Jan 5 00:02:00 GMT 2016


On 2016-01-04 23:55, Florian Weimer wrote:
>>> One suggestion is to make a non-terminated buffer undefined, but that
>>> breaks
>>> the snprintf analogy for size 0 inputs.

What happens in this case is more or less documented but "in practice 
this should not happen as it means that either dstsize is incorrect or 
that dst is not a proper string"[1] so it's not clear if glibc should 
support it officially. Making it UB seems to be a valid choice.

[1] 
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/strlcat.3?query=strlcpy&sec=3#x4445534352495054494f4e

>> Sorry, what analogy is that? snprintf does not concatenate to a buffer
>> directly. What is the practical use case here? How does the use case
>> ignore the principle that strlcpy should null-terminate its output?
>
> We can probably ditch the size-0 documented special case for strlcat
> (where it is just extremely confusing and not very helpful),

Yeah, this is strange. The full analogy with snprintf is documented for 
strlcpy only but I don't think it's implied for strlcat.

Plus, the implementation[2] in openbsd (the most upstream IIUC) does 
pointer arithmetic on the destination pointer which is UB for NULL. I 
guess this means that dst=NULL is not supposed to be supported.

[2] 
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlcat.c?rev=1.16&content-type=text/x-cvsweb-markup

> but not for
> strlcpy, where it is part of the specification.
>
> Apart from that, my only objection to your strlcpy text is this:
>
> +The behavior of @code{strlcpy} is undefined if @var{size} is zero, or
> +if the source and destination strings overlap.
>
> I think it should say “if the source string and destination array
> overlap”.   There is no destination string before the call.  I don't
> think it's necessary to make the special case defined where the source
> string is part of the destination array, but not located close to the
> beginning so that the actual copy will not overlap.  This is simply too
> subtle.   I think it is undefined for snprintf (“If copying takes place
> between objects that overlap, the behavior is undefined.”),although
> this does not necessarily follow from the restrict qualify (based on my
> somewhat shaky understanding of restrict).

IIUC you are saying that this code:

   char s[10];
   snprintf(s, -1, "%s", "abc");

is invalid. IMHO this is wrong. The description of snprintf in C11 
doesn't mention size of the destination array or talk about any 
connection between n and s at all, it just says that characters beyond 
the (n-1)st are discarded.

I think both strlcpy and strlcat should work just fine with size=-1. 
This is not a subtle point.

> I would like to make a similar change to your strlcat text:
>
> +The behavior is undefined if @var{to} does not contain a null byte in
> +its first @var{size} bytes, or if the source and resulting destination
> +strings overlap.
>
> There, it does make sense to speak of a string, but supporting the
> special case where the source overlaps with the destination array, but
> not the part that is written, is again very subtle and difficult to tell
> apart from the regular overlap.

Yeah, something like this:

   char *s = "abc";
   strlcat(s, s, 2);

:-)

-- 
Alexander Cherepanov



More information about the Libc-alpha mailing list