summaryrefslogtreecommitdiff
path: root/common/xasprintf.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/xasprintf.c')
-rw-r--r--common/xasprintf.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/common/xasprintf.c b/common/xasprintf.c
index 00ff66a..7e37e5b 100644
--- a/common/xasprintf.c
+++ b/common/xasprintf.c
@@ -1,5 +1,6 @@
/* xasprintf.c
* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ * Copyright (C) 2020 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -68,3 +69,55 @@ xtryasprintf (const char *fmt, ...)
return NULL;
return buf;
}
+
+
+/* This is safe version of realloc useful for reallocing a calloced
+ * array. There are two ways to call it: The first example
+ * reallocates the array A to N elements each of SIZE but does not
+ * clear the newly allocated elements:
+ *
+ * p = xtryreallocarray (a, n, n, nsize);
+ *
+ * Note that when NOLD is larger than N no cleaning is needed anyway.
+ * The second example reallocates an array of size NOLD to N elements
+ * each of SIZE but clear the newly allocated elements:
+ *
+ * p = xtryreallocarray (a, nold, n, nsize);
+ *
+ * Note that xtryreallocarray (NULL, 0, n, nsize) is equivalent to
+ * xtrycalloc (n, nsize).
+ *
+ * The same function under the name gpgrt_reallocarray exists in
+ * libgpg-error but only since version 1.38 and thus we use a copy
+ * here.
+ */
+void *
+xtryreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size)
+{
+ size_t oldbytes, bytes;
+ char *p;
+
+ bytes = nmemb * size; /* size_t is unsigned so the behavior on overflow
+ * is defined. */
+ if (size && bytes / size != nmemb)
+ {
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+
+ p = xtryrealloc (a, bytes);
+ if (p && oldnmemb < nmemb)
+ {
+ /* OLDNMEMBS is lower than NMEMB thus the user asked for a
+ calloc. Clear all newly allocated members. */
+ oldbytes = oldnmemb * size;
+ if (size && oldbytes / size != oldnmemb)
+ {
+ xfree (p);
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ memset (p + oldbytes, 0, bytes - oldbytes);
+ }
+ return p;
+}