aboutsummaryrefslogtreecommitdiffstats
path: root/src/init.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-03-03 14:41:39 +0000
committerWerner Koch <[email protected]>2020-03-03 14:41:39 +0000
commit969abd302211262562df93ae5412ee319aae69e6 (patch)
tree37fc4be7deab2afa11c86faf76f324ad15c7302f /src/init.c
parentcore: Fix allocation bug introduced with last commit. (diff)
downloadlibgpg-error-969abd302211262562df93ae5412ee319aae69e6.tar.gz
libgpg-error-969abd302211262562df93ae5412ee319aae69e6.zip
core: New function gpgrt_reallocarray.
* src/init.c (_gpgrt_reallocarray): New. * src/visibility.c (gpgrt_reallocarray): New. * src/gpg-error.vers, src/gpg-error.def.in: Add new function. * src/gpg-error.h.in: Add new interface. * tests/t-malloc.c: New. * tests/Makefile.am (TESTS): Add new test. -- Note that this function is different from the glibc function because it has an extra parameter which allows to clear the new elements. A realloc after a calloc with forgotten memset after it is a common source of error, thus we introduce this slightly different function. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'src/init.c')
-rw-r--r--src/init.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/src/init.c b/src/init.c
index 8ddf0c0..6239682 100644
--- a/src/init.c
+++ b/src/init.c
@@ -259,6 +259,55 @@ _gpgrt_realloc (void *a, size_t n)
}
+/* 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 gpgrt_reallocarray (NULL, 0, n, nsize) is equivalent to
+ * _gpgrt_calloc (n, nsize).
+ *
+ */
+void *
+_gpgrt_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 = _gpgrt_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;
+}
+
+
/* The malloc to be used for data returned by the public API. */
void *
_gpgrt_malloc (size_t n)