This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH v7] Implement strlcpy, strlcat [BZ #178]
- From: Alexander Cherepanov <ch3root at openwall dot com>
- To: Paul Eggert <eggert at cs dot ucla dot edu>, Florian Weimer <fweimer at redhat dot com>
- Cc: GNU C Library <libc-alpha at sourceware dot org>
- Date: Fri, 8 Jan 2016 22:27:43 +0300
- Subject: Re: [PATCH v7] Implement strlcpy, strlcat [BZ #178]
- Authentication-results: sourceware.org; auth=none
- References: <5682DD7E dot 6000301 at redhat dot com> <56839678 dot 8040304 at cs dot ucla dot edu> <568ADC5F dot 5010608 at redhat dot com> <568B1587 dot 4030905 at cs dot ucla dot edu> <568C08E1 dot 2010604 at redhat dot com> <568C3ED3 dot 1090405 at cs dot ucla dot edu>
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