Imported Upstream version 1.8.1p2
[debian/sudo] / common / alloc.c
diff --git a/common/alloc.c b/common/alloc.c
new file mode 100644 (file)
index 0000000..7fbf3c8
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1999-2005, 2007, 2010-2011
+ *     Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM 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.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRING_H */
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+
+#include "missing.h"
+#include "alloc.h"
+#include "error.h"
+
+/*
+ * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t
+ * could be signed (as it is on SunOS 4.x).  This just means that
+ * emalloc2() and erealloc3() cannot allocate huge amounts on such a
+ * platform but that is OK since sudo doesn't need to do so anyway.
+ */
+#ifndef SIZE_MAX
+# ifdef SIZE_T_MAX
+#  define SIZE_MAX     SIZE_T_MAX
+# else
+#  define SIZE_MAX     INT_MAX
+# endif /* SIZE_T_MAX */
+#endif /* SIZE_MAX */
+
+/*
+ * emalloc() calls the system malloc(3) and exits with an error if
+ * malloc(3) fails.
+ */
+void *
+emalloc(size_t size)
+{
+    void *ptr;
+
+    if (size == 0)
+       errorx(1, "internal error, tried to emalloc(0)");
+
+    if ((ptr = malloc(size)) == NULL)
+       errorx(1, "unable to allocate memory");
+    return ptr;
+}
+
+/*
+ * emalloc2() allocates nmemb * size bytes and exits with an error
+ * if overflow would occur or if the system malloc(3) fails.
+ */
+void *
+emalloc2(size_t nmemb, size_t size)
+{
+    void *ptr;
+
+    if (nmemb == 0 || size == 0)
+       errorx(1, "internal error, tried to emalloc2(0)");
+    if (nmemb > SIZE_MAX / size)
+       errorx(1, "internal error, emalloc2() overflow");
+
+    size *= nmemb;
+    if ((ptr = malloc(size)) == NULL)
+       errorx(1, "unable to allocate memory");
+    return ptr;
+}
+
+/*
+ * erealloc() calls the system realloc(3) and exits with an error if
+ * realloc(3) fails.  You can call erealloc() with a NULL pointer even
+ * if the system realloc(3) does not support this.
+ */
+void *
+erealloc(void *ptr, size_t size)
+{
+
+    if (size == 0)
+       errorx(1, "internal error, tried to erealloc(0)");
+
+    ptr = ptr ? realloc(ptr, size) : malloc(size);
+    if (ptr == NULL)
+       errorx(1, "unable to allocate memory");
+    return ptr;
+}
+
+/*
+ * erealloc3() realloc(3)s nmemb * size bytes and exits with an error
+ * if overflow would occur or if the system malloc(3)/realloc(3) fails.
+ * You can call erealloc() with a NULL pointer even if the system realloc(3)
+ * does not support this.
+ */
+void *
+erealloc3(void *ptr, size_t nmemb, size_t size)
+{
+
+    if (nmemb == 0 || size == 0)
+       errorx(1, "internal error, tried to erealloc3(0)");
+    if (nmemb > SIZE_MAX / size)
+       errorx(1, "internal error, erealloc3() overflow");
+
+    size *= nmemb;
+    ptr = ptr ? realloc(ptr, size) : malloc(size);
+    if (ptr == NULL)
+       errorx(1, "unable to allocate memory");
+    return ptr;
+}
+
+/*
+ * estrdup() is like strdup(3) except that it exits with an error if
+ * malloc(3) fails.  NOTE: unlike strdup(3), estrdup(NULL) is legal.
+ */
+char *
+estrdup(const char *src)
+{
+    char *dst = NULL;
+    size_t len;
+
+    if (src != NULL) {
+       len = strlen(src);
+       dst = (char *) emalloc(len + 1);
+       (void) memcpy(dst, src, len);
+       dst[len] = '\0';
+    }
+    return dst;
+}
+
+/*
+ * estrdup() is like strndup(3) except that it exits with an error if
+ * malloc(3) fails.  NOTE: unlike strdup(3), estrdup(NULL) is legal.
+ */
+char *
+estrndup(const char *src, size_t maxlen)
+{
+    char *dst = NULL;
+    size_t len;
+
+    if (src != NULL) {
+       len = strlen(src);
+       if (len > maxlen)
+           len = maxlen;
+       dst = (char *) emalloc(len + 1);
+       (void) memcpy(dst, src, len);
+       dst[len] = '\0';
+    }
+    return dst;
+}
+
+/*
+ * easprintf() calls vasprintf() and exits with an error if vasprintf()
+ * returns -1 (out of memory).
+ */
+int
+easprintf(char **ret, const char *fmt, ...)
+{
+    int len;
+    va_list ap;
+    va_start(ap, fmt);
+    len = vasprintf(ret, fmt, ap);
+    va_end(ap);
+
+    if (len == -1)
+       errorx(1, "unable to allocate memory");
+    return len;
+}
+
+/*
+ * evasprintf() calls vasprintf() and exits with an error if vasprintf()
+ * returns -1 (out of memory).
+ */
+int
+evasprintf(char **ret, const char *format, va_list args)
+{
+    int len;
+
+    if ((len = vasprintf(ret, format, args)) == -1)
+       errorx(1, "unable to allocate memory");
+    return len;
+}
+
+/*
+ * Wrapper for free(3) so we can depend on C89 semantics.
+ */
+void
+efree(void *ptr)
+{
+    if (ptr != NULL)
+       free(ptr);
+}