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

Paul Eggert eggert@cs.ucla.edu
Wed Dec 30 08:32:00 GMT 2015


Florian Weimer wrote:

> I got conflicting advice (on-list and off-list)

It might be helpful to see a summary of the off-list advice, as it appears to 
have influenced the proposed patch without leaving much trace of what was 
discussed. Did the off-list advisors consider the points raised on libc-alpha?

> One suggestion is to make a non-terminated buffer undefined, but that breaks
> the snprintf analogy for size 0 inputs.

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?

> Another option is to leave the
> array untouched (which is what I implemented and documented).

It is OK to *implement* it that way. But *documenting* this weird corner case 
would raise a can of worms. For example, it would mean strlcat's destination 
might not be a string, which would mean that the proposed documentation's talk 
about behavior being "undefined if the strings overlap" is not worded correctly. 
These problems are discussed in more detail below.

> I did not pick up
> the full criticism because glibc has repeatedly demonstrated that its
> recommended approach to string processing is rather error-prone, so we
> should not judge other approaches too harshly.

Fair enough. However, the wording in the latest proposal has the opposite 
problem: when documenting strncpy it inserts a seemingly-partisan suggestion to 
use strlcpy instead. Furthermore, its strlcpy and strlcat sections both promote 
these functions as ways to avoid buffer overruns even though strlcpy and strlcat 
are not on their face more effective at that than the other truncation 
functions. The strlcpy/strlcat documentation should be like the other truncation 
functions, and defer to the general wording about buffer overruns that is 
already in that section of the manual, rather than contain special advocacy for 
that particular approach.

Here are some other (in some cases, related) issues with the documentation 
change just proposed:

* It starts off by saying strcpy copies data that is "including a terminating 
null byte" but this is not true if SIZE is zero.

* The paragraph that specifies strlcpy semantics "If @var{size} is less than or 
equal to the the length of the string" is incorrect when SIZE is zero. The 
wording should be something more like "If @var{size} is nonzero and less than or 
equal to the the length of the string".

* It says strlcpy's behavior is undefined if the strings overlap, but if SIZE is 
zero there is no destination string. It should say the behavior is undefined if 
SIZE is nonzero and the strings overflap.

* When giving the differences between strncpy and strlcpy, it does not mention 
that strlcpy requires the source string to be null-terminated, nor that it 
computes the source string's length. Similarly when giving the differences 
between strncat and strlcat.

* The initial sentence describing strlcat assumes that the destination is a 
string, which is not necessarily the case.

* Typo: "If array @var{to}" should be "If the array @var{to}".

* The phrase "the length of the untruncated string" does not apply if the 
destination is not a string.

* On multiple occasions, the description for strlcat talks about "the length of 
the string @var{to}" without making it clear whether it is talking about the old 
length of TO, or about the new length.

* It does not mention that truncation in strlcat occurs when the result is 
greater than or equal to the size.

* It says that strlcat's behavior is undefined if the strings overlap, but the 
destination is not necessarily a string, and the description of overlap does not 
make it clear whether it's talking about the old destination string or array, 
the new destination string or array, or the modified part of the destination.

* When giving the differences between strncat and strlcat, it does not mention 
that strlcat ensures that an already-null-terminated destination stays 
null-terminated.

* The documentation does not state that it is OK for the destination pointer to 
be NULL if SIZE is zero.

* In some places the documentation says "length" (not counting the null 
terminator) when it is referring to size (counting the null terminator).


Fixing these problems would take some work and would complicate the 
documentation. Instead, I'll update my earlier patch (which leaves these weird 
corner case behavior undefined; this is considerably simpler), by removing the 
"full criticisms" that you mentioned and by adopting many of the other textual 
changes you made. This revised doc patch is shorter than before, and is 
compatible with the most-recently-proposed implementation.

As before I hope that the strlcpy/strlcat code changes do not go in, but if they 
do go in they will need proper documentation.

The first attachment is a patch relative to master; the second is a diff of 
string.texi compared to the text you just proposed.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Document-strlcpy-strlcat.patch
Type: text/x-diff
Size: 4934 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151230/8d2cad9e/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: string.texi.patch
Type: text/x-diff
Size: 5939 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151230/8d2cad9e/attachment-0001.bin>


More information about the Libc-alpha mailing list