]> eyrie.org Git - kerberos/krb5-strength.git/blobdiff - util/xmalloc.c
Update util/xmalloc.c from rra-c-util
[kerberos/krb5-strength.git] / util / xmalloc.c
index 5bfd5558589f2290a8c221a5747194a950dfac5c..2e3e1246a21f975d9fa066cc45ba8fa4b35cd71c 100644 (file)
@@ -12,7 +12,7 @@
  *      buffer = xmalloc(1024);
  *      xrealloc(buffer, 2048);
  *      free(buffer);
- *      buffer = xcalloc(1024);
+ *      buffer = xcalloc(1, 1024);
  *      free(buffer);
  *      buffer = xstrdup(string);
  *      free(buffer);
  * allocation function will try its allocation again (calling the handler
  * again if it still fails).
  *
+ * xreallocarray behaves the same as the OpenBSD reallocarray function but for
+ * the same error checking, which in turn is the same as realloc but with
+ * calloc-style arguments and size overflow checking.
+ *
  * xstrndup behaves like xstrdup but only copies the given number of
  * characters.  It allocates an additional byte over its second argument and
  * always nul-terminates the string.
  * line number to these functions.
  *
  * The canonical version of this file is maintained in the rra-c-util package,
- * which can be found at <http://www.eyrie.org/~eagle/software/rra-c-util/>.
+ * which can be found at <https://www.eyrie.org/~eagle/software/rra-c-util/>.
  *
- * Copyright 2012, 2013
+ * Written by Russ Allbery <eagle@eyrie.org>
+ * Copyright 2015, 2023 Russ Allbery <eagle@eyrie.org>
+ * Copyright 2012-2014
  *     The Board of Trustees of the Leland Stanford Junior University
- * Copyright (c) 2004, 2005, 2006
- *     by Internet Systems Consortium, Inc. ("ISC")
- * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- *     2002, 2003 by The Internet Software Consortium and Rich Salz
+ * Copyright 2004-2006 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright 1991, 1994-2003 The Internet Software Consortium and Rich Salz
  *
  * This code is derived from software contributed to the Internet Software
  * Consortium by Rich Salz.
@@ -79,6 +83,8 @@
  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  * PERFORMANCE OF THIS SOFTWARE.
+ *
+ * SPDX-License-Identifier: ISC
  */
 
 #include <config.h>
@@ -95,8 +101,8 @@ void
 xmalloc_fail(const char *function, size_t size, const char *file, int line)
 {
     if (size == 0)
-        sysdie("failed to format output with %s at %s line %d", function,
-               file, line);
+        sysdie("failed to format output with %s at %s line %d", function, file,
+               line);
     else
         sysdie("failed to %s %lu bytes at %s line %d", function,
                (unsigned long) size, file, line);
@@ -115,7 +121,7 @@ x_malloc(size_t size, const char *file, int line)
     real_size = (size > 0) ? size : 1;
     p = malloc(real_size);
     while (p == NULL) {
-        (*xmalloc_error_handler)("malloc", size, file, line);
+        xmalloc_error_handler("malloc", size, file, line);
         p = malloc(real_size);
     }
     return p;
@@ -131,7 +137,7 @@ x_calloc(size_t n, size_t size, const char *file, int line)
     size = (size > 0) ? size : 1;
     p = calloc(n, size);
     while (p == NULL) {
-        (*xmalloc_error_handler)("calloc", n * size, file, line);
+        xmalloc_error_handler("calloc", n * size, file, line);
         p = calloc(n, size);
     }
     return p;
@@ -144,11 +150,58 @@ x_realloc(void *p, size_t size, const char *file, int line)
     void *newp;
 
     newp = realloc(p, size);
-    while (newp == NULL && size > 0) {
-        (*xmalloc_error_handler)("realloc", size, file, line);
+    if (size == 0)
+        return newp;
+
+        /*
+         * GCC 13.2.0 (and some earlier versions) misdiagnose this error
+         * handling as a use-after-free of p, but the C standard guarantees
+         * that if realloc fails (which is true in every case when it returns
+         * NULL when size > 0), p is unchanged and still valid.
+         */
+#if __GNUC__ >= 12 && !defined(__clang__)
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
+    while (newp == NULL) {
+        xmalloc_error_handler("realloc", size, file, line);
         newp = realloc(p, size);
     }
     return newp;
+#if __GNUC__ >= 12 && !defined(__clang__)
+#    pragma GCC diagnostic pop
+#endif
+}
+
+
+void *
+x_reallocarray(void *p, size_t n, size_t size, const char *file, int line)
+{
+    void *newp;
+
+    newp = reallocarray(p, n, size);
+    if (size == 0 || n == 0)
+        return newp;
+
+        /*
+         * GCC 13.2.0 (and some earlier versions) misdiagnose this error
+         * handling as a use-after-free of p, but the documentation of
+         * reallocarray guarantees that if reallocarray fails (which is true in
+         * every case when it returns NULL when size > 0 and n > 0), p is
+         * unchanged and still valid.
+         */
+#if __GNUC__ >= 12 && !defined(__clang__)
+#    pragma GCC diagnostic push
+#    pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
+    while (newp == NULL) {
+        xmalloc_error_handler("reallocarray", n * size, file, line);
+        newp = reallocarray(p, n, size);
+    }
+#if __GNUC__ >= 12 && !defined(__clang__)
+#    pragma GCC diagnostic pop
+#endif
+    return newp;
 }
 
 
@@ -161,7 +214,7 @@ x_strdup(const char *s, const char *file, int line)
     len = strlen(s) + 1;
     p = malloc(len);
     while (p == NULL) {
-        (*xmalloc_error_handler)("strdup", len, file, line);
+        xmalloc_error_handler("strdup", len, file, line);
         p = malloc(len);
     }
     memcpy(p, s, len);
@@ -187,7 +240,7 @@ x_strndup(const char *s, size_t size, const char *file, int line)
     length = p - s;
     copy = malloc(length + 1);
     while (copy == NULL) {
-        (*xmalloc_error_handler)("strndup", length + 1, file, line);
+        xmalloc_error_handler("strndup", length + 1, file, line);
         copy = malloc(length + 1);
     }
     memcpy(copy, s, length);
@@ -211,7 +264,7 @@ x_vasprintf(char **strp, const char *fmt, va_list args, const char *file,
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
         status = (status < 0) ? 0 : status + 1;
-        (*xmalloc_error_handler)("vasprintf", status, file, line);
+        xmalloc_error_handler("vasprintf", status, file, line);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
@@ -235,13 +288,14 @@ x_asprintf(char **strp, const char *file, int line, const char *fmt, ...)
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
         status = (status < 0) ? 0 : status + 1;
-        (*xmalloc_error_handler)("asprintf", status, file, line);
+        xmalloc_error_handler("asprintf", status, file, line);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
     }
+    va_end(args);
 }
-#else /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
+#else  /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */
 void
 x_asprintf(char **strp, const char *fmt, ...)
 {
@@ -257,10 +311,11 @@ x_asprintf(char **strp, const char *fmt, ...)
         status = vsnprintf(NULL, 0, fmt, args_copy);
         va_end(args_copy);
         status = (status < 0) ? 0 : status + 1;
-        (*xmalloc_error_handler)("asprintf", status, __FILE__, __LINE__);
+        xmalloc_error_handler("asprintf", status, __FILE__, __LINE__);
         va_copy(args_copy, args);
         status = vasprintf(strp, fmt, args_copy);
         va_end(args_copy);
     }
+    va_end(args);
 }
 #endif /* !(HAVE_C99_VAMACROS || HAVE_GNU_VAMACROS) */