]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
lib/string/: Redesign stpecpy() and stpeprintf()
authorAlejandro Colomar <alx@kernel.org>
Sat, 8 Feb 2025 13:41:16 +0000 (14:41 +0100)
committerAlejandro Colomar <foss+github@alejandro-colomar.es>
Fri, 15 May 2026 10:06:49 +0000 (12:06 +0200)
Make them report truncation via errno and NULL.

Instead of having three possible returns (a pointer to the NUL byte, the
end of the array, or NULL), reduce it to two possible ones: one for
success, and one for error.

Use errno, which is a common way to signal the specific error, and thus
treat truncation as any other error.  This simplifies error handling
after these calls.  Also, if one misuses a pointer after truncation, the
results are better if the pointer is NULL: the program will easily
abort.  If we returned 'end', the program could more easily produce a
buffer overrun.

Suggested-by: Douglas McIlroy <douglas.mcilroy@dartmouth.edu>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
lib/string/sprintf/stpeprintf.h
lib/string/strcpy/stpecpy.h

index b0048c4441d5ed5bcce8aa5a8d4548c9b2cec0e7..19987caaaad3324d554b72a2fb0a8cd36558f7ac 100644 (file)
@@ -10,9 +10,9 @@
 
 #include <stdarg.h>
 #include <stddef.h>
-#include <stdio.h>
 
 #include "attr.h"
+#include "string/sprintf/snprintf.h"
 
 
 #if !defined(HAVE_STPEPRINTF)
@@ -57,20 +57,17 @@ inline char *vstpeprintf(char *dst, char *end, const char *restrict fmt,
  *
  * RETURN VALUE
  *     dst + strlen(dst)
- *             •  On success, these functions return a pointer to the
- *                terminating NUL byte.
+ *             On success, these functions return a pointer to the
+ *             terminating NUL byte.
  *
- *     end
- *             •  If this call truncated the resulting string.
- *             •  If `dst == end` (a previous chained call to these
- *                functions truncated).
- *     NULL
- *             •  If this function failed (see ERRORS).
- *             •  If `dst == NULL` (a previous chained call to these
- *                functions failed).
+ *     NULL    On error.
  *
  * ERRORS
+ *     E2BIG   The string was truncated.
+ *
  *     These functions may fail for the same reasons as vsnprintf(3).
+ *
+ *     If dst is NULL at input, this function doesn't clobber errno.
  */
 
 
@@ -97,18 +94,13 @@ vstpeprintf(char *dst, char *end, const char *restrict fmt, va_list ap)
        int        len;
        ptrdiff_t  size;
 
-       if (dst == end)
-               return end;
        if (dst == NULL)
                return NULL;
 
        size = end - dst;
-       len = vsnprintf(dst, size, fmt, ap);
-
+       len = vsnprintf_(dst, size, fmt, ap);
        if (len == -1)
                return NULL;
-       if (len >= size)
-               return end;
 
        return dst + len;
 }
index 91c6ce7a7fbb7eaf810d4f4443d235a3687031ef..6719bb2a133f58f61a7cc8b22ad9edcecdc670a5 100644 (file)
@@ -8,6 +8,7 @@
 
 #include "config.h"
 
+#include <errno.h>
 #include <stdbool.h>
 #include <stddef.h>
 #include <string.h>
@@ -47,19 +48,15 @@ inline char *stpecpy(char *dst, char *end, const char *restrict src);
  *
  * RETURN VALUE
  *     dst + strlen(dst)
- *             •  On success, this function returns a pointer to the
- *                terminating NUL byte.
+ *             On success, this function returns a pointer to the
+ *             terminating NUL byte.
  *
- *     end
- *             •  If this call truncated the resulting string.
- *             •  If `dst == end` (a previous chained call to these
- *                functions truncated).
- *     NULL
- *             •  If `dst == NULL` (a previous chained call to
- *                [v]stpeprintf() failed).
+ *     NULL    On error.
  *
  * ERRORS
- *     This function doesn't set errno.
+ *     E2BIG   The string was truncated.
+ *
+ *     If dst is NULL at input, this function doesn't clobber errno.
  */
 
 
@@ -68,10 +65,9 @@ inline char *
 stpecpy(char *dst, char *end, const char *restrict src)
 {
        bool    trunc;
+       char    *p;
        size_t  dsize, dlen, slen;
 
-       if (dst == end)
-               return end;
        if (dst == NULL)
                return NULL;
 
@@ -80,7 +76,13 @@ stpecpy(char *dst, char *end, const char *restrict src)
        trunc = (slen == dsize);
        dlen = slen - trunc;
 
-       return stpcpy(mempcpy(dst, src, dlen), "") + trunc;
+       p = stpcpy(mempcpy(dst, src, dlen), "");
+       if (trunc) {
+               errno = E2BIG;
+               return NULL;
+       }
+
+       return p;
 }
 #endif