[PATCH] Implement strlcat [BZ#178]

Paul Eggert eggert@cs.ucla.edu
Thu Dec 3 17:33:00 GMT 2015


Thanks for the review.  Revised patchset attached.  At this point I'm 
inclined to install the first two patches (which don't change semantics) 
to make it easier to review and maintain the third one (which adds 
strlcpy+strlcat), but I'll hold off a bit longer on that to get more 
feedback.

Replying to your comments:
> I don't understand the “and as for strings usually pointers … are used”
> part.

Changed to "A wide-string variable is usually declared to be a pointer 
of type @code{wchar_t *}, by analogy with string variables and 
@code{char *}." Hope this makes it clear.

> Standard uses “wide string” by the way, not “wide character string”.

C11 says "wide string", POSIX says "wide-character string". True, the 
more-concise form is better here, so I've changed it to that. Similarly, 
I changed "multibyte character string" (POSIX wording) to "multibyte 
string" (C Standard wording). I wish the standards could standardize the 
wording...

> Please also use “integer constant @code{0}”.  Only the integer constant
> zero represents a null pointer, an integer variable which stores the
> value zero does not.

Done.

> +literal.  Strings can also be formed by @dfn{string concatenation}:
> +@code{"a" "b"} is the
>
> The original had “string literal”.  As this only works for string
> literals, it's best to keep it.

The original was incorrect; it said "string literals can also be formed 
by @dfn{string concatenation}" but string literals are the input to 
string concatenation, not the output from it. I changed the wording to 
"String literals can also contribute to @dfn{string concatenation}:...".

>   blocks of memory, and functions that are specific to null-terminated
> -arrays of characters and wide characters.
> +strings and wide strings.
>
> Should be “specific to strings and wide character strings” (the
> “null-terminated” is redundant,
OK, though this will be "wide strings" as per the above-described changed.
> and “wide strings” has not been defined.
>
> Most of the remaining “null-terminated” occurrences in string.texi
> should be removed, for consistency and clarity.

Sure, done.

> @@ -309,7 +318,8 @@ returns @var{maxlen}.  Therefore this function is
> equivalent to
>   @code{(strlen (@var{s}) < @var{maxlen} ? strlen (@var{s}) : @var{maxlen})}
>   but it
>   is more efficient and works even if the string @var{s} is not
> -null-terminated.
> +null-terminated so long as @var{maxlen} does not exceed the
> +size of @var{s}'s array.
>
> This doesn't make much sense anymore because strings are defined to be
> always null-terminated.

Reworded to "If the array @var{s} of size @var{maxlen} contains a null 
byte, the @code{strnlen} function returns the length of the string 
@var{s} in bytes.  Otherwise it returns @var{maxlen}. Therefore this 
function is equivalent to @code{(strlen (@var{s}) < @var{maxlen} ? 
strlen (@var{s}) : @var{maxlen})} but it is more efficient and works 
even if @var{s} is not null-terminated so long as @var{maxlen} does not 
exceed the size of @var{s}'s array."


>
>> PS.  This time around I noticed that in some cases strlcat is required
>> to not null-terminate its output, even when there's room for a null byte
>> in the destination buffer.  Eeeuuuw.  Do we really want to document that
>> particular misfeature?  Does user code really require it?
> It's part of the specification, as far as I can tell.

Yes and no. The FreeBSD man page says that "for strlcat() both src and 
dst must be NUL-terminated"; see 
<https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3>. 
Admittedly the FreeBSD spec is confused here, as the second part of its 
RETURN VALUES section describes what happens when the destination is not 
null-terminated! But that section also says "this should not happen", 
and obviously user code should not depend on behavior that "should not 
happen" and in practice I expect user code follows this, so let's go 
with the slightly-tighter spec.

Come to think of it, this is related to the confusion between one of the 
main goals of strlcpy (namely, the result is always null-terminated), 
and the weird special case where the destination size is zero (where 
strlcpy cannot null-terminate the destination). In practice user code 
does not and should not depend on this weird special case. We can fix 
this confusion by making strlcpy have undefined behavior if the 
destination size is zero. This simplifies the spec, and gives us an 
opportunity to add one more runtime sanity check that the destination 
size is nonzero in our debugging implementation, if we want to do that. 
I've added this idea to the third patch in the attached patchset (which 
changes only the documentation).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Consistency-about-byte-vs-character-in-string.texi.patch
Type: text/x-patch
Size: 66051 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151203/2dc9a9e4/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0002-Split-large-string-section-add-truncation-advice.patch
Type: text/x-patch
Size: 28746 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151203/2dc9a9e4/attachment-0001.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-Add-strlcpy-strlcat.patch
Type: text/x-patch
Size: 6134 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/libc-alpha/attachments/20151203/2dc9a9e4/attachment-0002.bin>


More information about the Libc-alpha mailing list