[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