aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/gpg-error.def.in2
-rw-r--r--src/gpg-error.h.in1
-rw-r--r--src/gpg-error.vers1
-rw-r--r--src/gpgrt-int.h2
-rw-r--r--src/init.c49
-rw-r--r--src/visibility.c6
-rw-r--r--src/visibility.h2
7 files changed, 63 insertions, 0 deletions
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index bc4b0cc..bf8773b 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -235,4 +235,6 @@ EXPORTS
gpgrt_fnameconcat @178
gpgrt_absfnameconcat @179
+ gpgrt_reallocarray @180
+
;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index 5643bdf..b0b1972 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -466,6 +466,7 @@ gpg_error_from_syserror (void)
*/
void *gpgrt_realloc (void *a, size_t n);
+void *gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size);
void *gpgrt_malloc (size_t n);
void *gpgrt_calloc (size_t n, size_t m);
char *gpgrt_strdup (const char *string);
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 347235f..ab3bbb0 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -158,6 +158,7 @@ GPG_ERROR_1.0 {
_gpgrt_log_assert;
gpgrt_realloc;
+ gpgrt_reallocarray;
gpgrt_malloc;
gpgrt_calloc;
gpgrt_strdup;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index beb55ac..cc22004 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -114,6 +114,7 @@ void _gpgrt_abort (void) GPGRT_ATTR_NORETURN;
void _gpgrt_set_alloc_func (void *(*f)(void *a, size_t n));
void *_gpgrt_realloc (void *a, size_t n);
+void *_gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size);
void *_gpgrt_malloc (size_t n);
void *_gpgrt_calloc (size_t n, size_t m);
char *_gpgrt_strdup (const char *string);
@@ -126,6 +127,7 @@ char *_gpgrt_strconcat_core (const char *s1, va_list arg_ptr);
#define xtrymalloc(a) _gpgrt_malloc ((a))
#define xtrycalloc(a,b) _gpgrt_calloc ((a),(b))
#define xtryrealloc(a,b) _gpgrt_realloc ((a),(b))
+#define xtryreallocarray(a,b,c,d) _gpgrt_reallocarray ((a),(b),(c),(d))
#define xtrystrdup(a) _gpgrt_strdup ((a))
void _gpgrt_pre_syscall (void);
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)
diff --git a/src/visibility.c b/src/visibility.c
index ea55d54..2e6aed7 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -764,6 +764,12 @@ gpgrt_realloc (void *a, size_t n)
}
void *
+gpgrt_reallocarray (void *a, size_t oldnmemb, size_t nmemb, size_t size)
+{
+ return _gpgrt_reallocarray (a, oldnmemb, nmemb, size);
+}
+
+void *
gpgrt_malloc (size_t n)
{
return _gpgrt_malloc (n);
diff --git a/src/visibility.h b/src/visibility.h
index 0759d2f..f7d16be 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -152,6 +152,7 @@ MARK_VISIBLE (gpgrt_get_syscall_clamp)
MARK_VISIBLE (gpgrt_set_alloc_func)
MARK_VISIBLE (gpgrt_realloc)
+MARK_VISIBLE (gpgrt_reallocarray)
MARK_VISIBLE (gpgrt_malloc)
MARK_VISIBLE (gpgrt_calloc)
MARK_VISIBLE (gpgrt_strdup)
@@ -333,6 +334,7 @@ MARK_VISIBLE (gpgrt_absfnameconcat);
#define gpgrt_vsnprintf _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_realloc _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_reallocarray _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_malloc _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_calloc _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_strdup _gpgrt_USE_UNDERSCORED_FUNCTION