From f0d034ebf4fc299c2a6097248f51c329e65d2976 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 5 Mar 2020 16:23:52 +0100 Subject: [PATCH] common: New function xreallocarray * common/miscellaneous.c (gnupg_reallocarray): New. (xreallocarray): New. -- Taken from libgpg-error so that we can build with older versions of libgpg-error. --- common/miscellaneous.c | 59 ++++++++++++++++++++++++++++++++++++++++++ common/util.h | 4 +++ 2 files changed, 63 insertions(+) diff --git a/common/miscellaneous.c b/common/miscellaneous.c index af1f277af..e40dcd55f 100644 --- a/common/miscellaneous.c +++ b/common/miscellaneous.c @@ -117,6 +117,65 @@ xoutofcore (void) } +/* 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 = gpgrt_reallocarray (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 = gpgrt_reallocarray (a, nold, n, nsize); + * + * Note that gnupg_reallocarray (NULL, 0, n, nsize) is equivalent to + * gcry_calloc (n, nsize). + */ +void * +gnupg_reallocarray (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 = gcry_realloc (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; +} + + +/* Die-on-error version of gnupg_reallocarray. */ +void * +xreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size) +{ + void *p = gnupg_reallocarray (a, oldnmemb, nmemb, size); + if (!p) + xoutofcore (); + return p; +} + + /* A wrapper around gcry_cipher_algo_name to return the string "AES-128" instead of "AES". Given that we have an alias in libgcrypt for it, it does not harm to too much to return this other diff --git a/common/util.h b/common/util.h index 5778b7d6e..9f46457ba 100644 --- a/common/util.h +++ b/common/util.h @@ -314,6 +314,10 @@ void setup_libgcrypt_logging (void); /* Print an out of core message and die. */ void xoutofcore (void); +/* Array allocation. */ +void *gnupg_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); +void *xreallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size); + /* Same as estream_asprintf but die on memory failure. */ char *xasprintf (const char *fmt, ...) GPGRT_ATTR_PRINTF(1,2); /* This is now an alias to estream_asprintf. */