[PATCH v7] Implement strlcpy, strlcat [BZ #178]
Alexander Cherepanov
ch3root@openwall.com
Fri Jan 8 19:27:00 GMT 2016
On 2016-01-06 01:08, Paul Eggert wrote:
>> For strlcpy, we don't care if the destination is a string or not
>> because we overwrite what's in the destination array.
>
> No, applications that call strlcpy expect it to create a string. For
> example, the design intent is for applications to use strlcpy followed
> by strlcat, and because strlcat (S, ...) assumes that S is a string,
> strlcpy must create a string in S; otherwise the two functions would not
> be the companion functions that they're clearly supposed to be.
Perhaps this is not the only way to use strlcpy? It seems the case of
strlcpy with size=0 is special.
Let's consider a couple of use cases.
1. strlcpy followed by strlcat. This is what you are talking about, and
you want to keep the freedom to redefine these function, e.g., to crash
when size is 0. But this use case implies the same size in all calls to
these function. Hence you can catch size=0 with strlcat even if strlcpy
accepts size=0 without triggering any protections.
2. strlcpy with a retry. If you try to copy a string into a buffer and
there is not enough memory you can allocate more memory and retry
copying. Something like this:
void strlcpy_with_growing(char **dest, const char *src, size_t *size)
{
size_t len = strlcpy(*dest, src, *size);
if (len >= *size)
{
free(*dest);
*dest = xmalloc(len);
*size = len;
strlcpy(*dest, src, len);
}
}
Then it's handy to permit to start with a null pointer and a zero size.
Think of realloc which accepts a null pointer as input.
strlcpy with a retry is also one the intended uses of strlcpy: "Thus, if
truncation has occurred, the number of bytes needed to store the entire
string is now known and the programmer may allocate more space and
re-copy the strings if he or she wishes."[1]
[1] https://www.sudo.ws/todd/papers/strlcpy.html
Unrelatedly, it turned out useful to look into what valgrind does for
strlcpy. Apparently, Solaris actively uses strlcpy with size=0. From [2]:
/* This is just a fancy way how to write strlen(src).
Undocumented but heavily used. */
copied = strlcpy(NULL, src, 0);
See also [3].
[2]
https://sources.debian.net/src/valgrind/1:3.11.0-1/memcheck/tests/solaris/strlcpy.c/?hl=34:36#L34
[3]
https://sources.debian.net/src/valgrind/1:3.11.0-1/shared/vg_replace_strmem.c/#L563
I'm not arguing for any specific way to define strlcpy, just feeling
that the current discussion is not sufficiently informed.
--
Alexander Cherepanov
More information about the Libc-alpha
mailing list