implement reallocarray(3)

Submitted by Ariadne Conill on July 22, 2020, 12:24 a.m.

Details

Message ID 20200722002426.23580-1-ariadne@dereferenced.org
State New
Series "implement reallocarray(3)"
Headers show

Commit Message

Ariadne Conill July 22, 2020, 12:24 a.m.
reallocarray(3) is an extension introduced by OpenBSD, which
introduces calloc(3) overflow checking to realloc(3).

glibc 2.28 introduced support for this function behind _GNU_SOURCE,
while glibc 2.29 allows its usage in _DEFAULT_SOURCE, so I made it
available by default as well.
---
 include/stdlib.h          |  1 +
 src/malloc/reallocarray.c | 13 +++++++++++++
 2 files changed, 14 insertions(+)
 create mode 100644 src/malloc/reallocarray.c

Patch hide | download patch | download mbox

diff --git a/include/stdlib.h b/include/stdlib.h
index 194c2033..8db8e5cc 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -38,6 +38,7 @@  void srand (unsigned);
 void *malloc (size_t);
 void *calloc (size_t, size_t);
 void *realloc (void *, size_t);
+void *reallocarray (void *, size_t, size_t);
 void free (void *);
 void *aligned_alloc(size_t, size_t);
 
diff --git a/src/malloc/reallocarray.c b/src/malloc/reallocarray.c
new file mode 100644
index 00000000..733cb16a
--- /dev/null
+++ b/src/malloc/reallocarray.c
@@ -0,0 +1,13 @@ 
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+void *reallocarray(void *ptr, size_t m, size_t n)
+{
+	if (n && m > (size_t) -1 / n) {
+		errno = ENOMEM;
+		return NULL;
+	}
+
+	return realloc(ptr, m * n);
+}

Comments

Rich Felker July 22, 2020, 12:33 a.m.
On Tue, Jul 21, 2020 at 06:24:26PM -0600, Ariadne Conill wrote:
> reallocarray(3) is an extension introduced by OpenBSD, which
> introduces calloc(3) overflow checking to realloc(3).
> 
> glibc 2.28 introduced support for this function behind _GNU_SOURCE,
> while glibc 2.29 allows its usage in _DEFAULT_SOURCE, so I made it
> available by default as well.
> ---
>  include/stdlib.h          |  1 +
>  src/malloc/reallocarray.c | 13 +++++++++++++
>  2 files changed, 14 insertions(+)
>  create mode 100644 src/malloc/reallocarray.c
> 
> diff --git a/include/stdlib.h b/include/stdlib.h
> index 194c2033..8db8e5cc 100644
> --- a/include/stdlib.h
> +++ b/include/stdlib.h
> @@ -38,6 +38,7 @@ void srand (unsigned);
>  void *malloc (size_t);
>  void *calloc (size_t, size_t);
>  void *realloc (void *, size_t);
> +void *reallocarray (void *, size_t, size_t);
>  void free (void *);
>  void *aligned_alloc(size_t, size_t);

The declaration has to be in a suitably FTM-protected section of
stdlib.h not here (under _BSD_SOURCE, which is equivalent to
_DEFAULT_SOURCE).

> diff --git a/src/malloc/reallocarray.c b/src/malloc/reallocarray.c
> new file mode 100644
> index 00000000..733cb16a
> --- /dev/null
> +++ b/src/malloc/reallocarray.c
> @@ -0,0 +1,13 @@
> +#include <errno.h>
> +#include <stdint.h>
> +#include <stdlib.h>

And the appropriate FTM (_BSD_SOURCE) should be defined at the top
here so that the declaration is visible for the compiler to check
against the definition. Also stdint.h seems not to be needed.

> +void *reallocarray(void *ptr, size_t m, size_t n)
> +{
> +	if (n && m > (size_t) -1 / n) {
> +		errno = ENOMEM;
> +		return NULL;
> +	}

And 0 is preferred over NULL in musl, and no space after the cast
operator... although really the preferred style is no cast at all, and
I'm not sure how calloc ended up with one.

> +
> +	return realloc(ptr, m * n);
> +}
> -- 
> 2.27.0