Fix strlcpy in kernel, add strlcat.
authorDan Cross <crossd@gmail.com>
Thu, 15 Oct 2015 20:51:55 +0000 (16:51 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Wed, 28 Oct 2015 16:20:48 +0000 (12:20 -0400)
The return value of strlcpy was incorrect: it was returning
the amount it had copied, but the return value is supposed to
be the size of the input string.

I also added strlcat (with a prodigious comment, as the code
is subtle) for parity.

Nothing was checking the return value of strlcpy as far as I
could see, and while it's not specified by e.g. ANSI/ISO, it
still makes sense for us to follow the specification of other
implementations.

Tested: Rebuilt the kernel and ran Akaros.

References:
http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man3/strlcat.3?query=strlcpy&sec=3
http://www.sudo.ws/todd/papers/strlcpy.html

Signed-off-by: Dan Cross <crossd@gmail.com>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/string.h
kern/src/string.c

index 1c4020f..efcc890 100644 (file)
@@ -13,6 +13,7 @@ STRING        strcat(STRING dst, const STRING src);
 */
 char *strncpy(char *dst, const char *src, size_t size);
 size_t strlcpy(char *dst, const char *src, size_t size);
+size_t strlcat(char *dst, const char *src, size_t size);
 int    strcmp(const char *s1, const char *s2);
 int    strncmp(const char *s1, const char *s2, size_t size);
 int cistrcmp(char *s1, char *s2);
index 6964240..9d9bf6d 100644 (file)
@@ -63,15 +63,39 @@ strncpy(char *dst, const char *src, size_t size) {
 size_t
 strlcpy(char *dst, const char *src, size_t size)
 {
-       char *dst_in;
-
-       dst_in = dst;
        if (size > 0) {
                while (--size > 0 && *src != '\0')
                        *dst++ = *src++;
                *dst = '\0';
        }
-       return dst - dst_in;
+
+       return strlen(src);
+}
+
+size_t
+strlcat(char *dst, const char *src, size_t size)
+{
+       size_t rem;     /* Buffer space remaining after null in dst. */
+
+       /* We must find the terminating NUL byte in dst, but abort the
+        * search if we go past 'size' bytes.  At the end of this loop,
+        * 'dst' will point to either the NUL byte in the original
+        * destination or to one byte beyond the end of the buffer.
+        *
+        * 'rem' will be the amount of 'size' remaining beyond the NUL byte;
+        * potentially zero. This implies that 'size - rem' is equal to the
+        * distance from the beginning of the destination buffer to 'dst'.
+        *
+        * The return value of strlcat is the sum of the length of the
+        * original destination buffer (size - rem) plus the size of the
+        * src string (the return value of strlcpy). */
+       rem = size;
+       while ((rem > 0) && (*dst != '\0')) {
+               rem--;
+               dst++;
+       }
+
+       return (size - rem) + strlcpy(dst, src, rem);
 }
 
 int