]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/strlcpy.[ch]: Implement strtcpy(3) to replace strlcpy_()
authorAlejandro Colomar <alx@kernel.org>
Sun, 12 Nov 2023 12:43:32 +0000 (13:43 +0100)
committerIker Pedrosa <ikerpedrosam@gmail.com>
Wed, 22 Nov 2023 11:55:26 +0000 (12:55 +0100)
There's been a very long and interesting discussion in linux-man@ and
libc-alpha@, where we've discussed all the string-copying functions,
their pros and cons, when should each be used and avoided, etc.

Paul Eggert pointed out an important problem of strlcpy(3): it is
vulnerable to DoS attacks if an attacker controls the length of the
source string.  And even if it doesn't control it, the function is dead
slow (because its API forces it to calculate strlen(src)).

We've agreed that the general solution for a truncating string-copying
function is to write a wrapper over strnlen(3)+memcpy(3), which is
limited to strnlen(src, sizeof(dst)).  This is not vulnerable to DoS,
and is very fast for all buffer sizes.  string_copying(7) has been
updated to reflect this, and provides a reference implementation for
this wrapper function.

This strtcpy(3) (t for truncation) wrapper happens to have the same API
that our strlcpy_() function had, so replace it with the better
implementation.  We don't need to update callers nor tests, since the
API is the same.

A future commit will rename STRLCPY() to STRTCPY(), and replace
remaining calls to strlcpy(3) by calls to this strtcpy(3).

Link: <https://lore.kernel.org/linux-man/ZU4SDh-Se5gjPny5@debian/T/#mfb5a3fdeb35487dec6f8d9e3d8548bd0d92c4975/>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/strlcpy.c
lib/strlcpy.h
tests/unit/Makefile.am

index ffb83e0ceea4e4aae5d308606107b2371f12e469..58773b71567a0009e68635004c16b596125e61f4 100644 (file)
@@ -14,5 +14,5 @@
 #include "strlcpy.h"
 
 
-extern inline ssize_t strlcpy_(char *restrict dst, const char *restrict src,
-    size_t size);
+extern inline ssize_t strtcpy(char *restrict dst, const char *restrict src,
+    size_t dsize);
index c44819c6b3f9ba04d98d1a7a477f483dc311818e..36d847c4453f583959f6ee65f952f6160067c161 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <config.h>
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
 #include <sys/types.h>
  */
 
 
-#define STRLCPY(dst, src)  strlcpy_(dst, src, SIZEOF_ARRAY(dst))
+#define STRLCPY(dst, src)  strtcpy(dst, src, SIZEOF_ARRAY(dst))
 
 
-inline ssize_t strlcpy_(char *restrict dst, const char *restrict src,
-    size_t size);
+inline ssize_t strtcpy(char *restrict dst, const char *restrict src,
+    size_t dsize);
 
 
 inline ssize_t
-strlcpy_(char *restrict dst, const char *restrict src, size_t size)
+strtcpy(char *restrict dst, const char *restrict src, size_t dsize)
 {
-       size_t  len;
+       bool    trunc;
+       char    *p;
+       size_t  dlen, slen;
 
-       len = strlcpy(dst, src, size);
+       if (dsize == 0)
+               return -1;
 
-       return (len >= size) ? -1 : len;
+       slen = strnlen(src, dsize);
+       trunc = (slen == dsize);
+       dlen = slen - trunc;
+
+       p = mempcpy(dst, src, dlen);
+       *p = '\0';
+
+       return trunc ? -1 : slen;
 }
 
 
index e209f041396b058ba124b6f5f6d8f710af964f0a..46794d66614681399c327c97491317245e24af56 100644 (file)
@@ -38,13 +38,11 @@ test_strlcpy_SOURCES = \
     $(NULL)
 test_strlcpy_CFLAGS = \
     $(AM_FLAGS) \
-    $(LIBBSD_CFLAGS) \
     $(NULL)
 test_strlcpy_LDFLAGS = \
     $(NULL)
 test_strlcpy_LDADD = \
     $(CMOCKA_LIBS) \
-    $(LIBBSD_LIBS) \
     $(NULL)
 
 test_xasprintf_SOURCES = \