From 6e29434596508263dde7f21198df1e76de89ab8b Mon Sep 17 00:00:00 2001 From: Darshit Shah Date: Wed, 9 Aug 2017 10:55:12 +0200 Subject: [PATCH] Add new module reallocarray --- ChangeLog | 16 +++++++++++ MODULES.html.sh | 1 + doc/glibc-functions/reallocarray.texi | 21 ++++++++++++++ lib/reallocarray.c | 37 +++++++++++++++++++++++++ lib/stdlib.in.h | 17 ++++++++++++ m4/reallocarray.m4 | 20 ++++++++++++++ m4/stdlib_h.m4 | 8 ++++-- modules/reallocarray | 32 +++++++++++++++++++++ modules/reallocarray-tests | 11 ++++++++ modules/stdlib | 2 ++ tests/test-reallocarray.c | 52 +++++++++++++++++++++++++++++++++++ 11 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 doc/glibc-functions/reallocarray.texi create mode 100644 lib/reallocarray.c create mode 100644 m4/reallocarray.m4 create mode 100644 modules/reallocarray create mode 100644 modules/reallocarray-tests create mode 100644 tests/test-reallocarray.c diff --git a/ChangeLog b/ChangeLog index 6c418dfe1..dd943b428 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2017-08-09 Darshit Shah + + reallocarray: New module + reallocarray is a new function in glibc 2.26 to safely allocate an array of + memory locations with integer overflow protection. + * MODULES.html.sh: Add reallocarray. + * doc/glibc-functions/reallocarray.texi: Documentation for reallocarray. + * lib/reallocarray.c: New file to implement module reallocarray. + * lib/stdlib.in.h: Add function declarations for reallocarray. + * m4/reallocarray.m4: New file + * m4/stdlib_h.m4: Declare reallocarray + * modules/reallocarray: New file + * modules/reallocarray-test: New file + * modules/stdlib: Coerce stdlib.h to export reallocarray() + * tests/test-reallocarray.c: New test + 2017-08-08 Paul Eggert extensions: add _OPENBSD_SOURCE diff --git a/MODULES.html.sh b/MODULES.html.sh index a64b9997e..1a258b632 100755 --- a/MODULES.html.sh +++ b/MODULES.html.sh @@ -1703,6 +1703,7 @@ func_all_modules () func_module free func_module malloc-gnu func_module realloc-gnu + func_module reallocarray func_module pagealign_alloc func_end_table diff --git a/doc/glibc-functions/reallocarray.texi b/doc/glibc-functions/reallocarray.texi new file mode 100644 index 000000000..3d42f0667 --- /dev/null +++ b/doc/glibc-functions/reallocarray.texi @@ -0,0 +1,21 @@ address@hidden reallocarray address@hidden @code{reallocarray} address@hidden reallocarray + +Gnulib module: reallocarray + +Allocate multiple memory locations of a fixed size with integer overflow +protection. +Glibc Manual: @url{https://www.gnu.org/software/libc/manual/html_node/Changing-Block-Size.html#Changing-Block-Size} + +Portability problems fixed by Gnulib: address@hidden address@hidden +This function is missing on all non-glibc platforms: glibc 2.25, Mac OS X 10.5, +FreeBSD 6.0, NetBSD 5.0, OpenBSD 3.8, Minix 3.1.8, AIX 5.1, HP-UX 11, IRIX 6.5, +OSF/1 5.1, Solaris 11 2011-11, Cygwin, mingw, MSVC 14, Interix 3.5, BeOS. address@hidden itemize + +Portability problems not fixed by Gnulib: address@hidden address@hidden itemize diff --git a/lib/reallocarray.c b/lib/reallocarray.c new file mode 100644 index 000000000..05357a443 --- /dev/null +++ b/lib/reallocarray.c @@ -0,0 +1,37 @@ +/* reallocarray() function that is glibc compatible. + + Copyright (C) 2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* written by Darshit Shah */ + +#include + +#include +#include + +#include "xalloc-oversized.h" + +void * +reallocarray(void *ptr, size_t nmemb, size_t size) +{ + if (xalloc_oversized (nmemb, size)) + { + errno = ENOMEM; + return NULL; + } + /* We rely on using the semantics of the GNU realloc() function here. */ + return realloc(ptr, nmemb * size); +} diff --git a/lib/stdlib.in.h b/lib/stdlib.in.h index b5cf9d369..c6e68fddc 100644 --- a/lib/stdlib.in.h +++ b/lib/stdlib.in.h @@ -765,6 +765,23 @@ _GL_WARN_ON_USE (realloc, "realloc is not POSIX compliant everywhere - " "use gnulib module realloc-posix for portability"); #endif + +#if @GNULIB_REALLOCARRAY@ +# if ! @HAVE_REALLOCARRAY@ +_GL_FUNCDECL_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +# endif +_GL_CXXALIAS_SYS (reallocarray, void *, + (void *ptr, size_t nmemb, size_t size)); +_GL_CXXALIASWARN (reallocarray); +#elif defined GNULIB_POSIXCHECK +# undef reallocarray +# if HAVE_RAW_DECL_REALLOCARRAY +_GL_WARN_ON_USE (reallocarray, "reallocarray is not portable - " + "use gnulib module reallocarray for portability"); +# endif +#endif + #if @GNULIB_REALPATH@ # if @REPLACE_REALPATH@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) diff --git a/m4/reallocarray.m4 b/m4/reallocarray.m4 new file mode 100644 index 000000000..261df7a90 --- /dev/null +++ b/m4/reallocarray.m4 @@ -0,0 +1,20 @@ +# reallocarray.m4 serial 1 +dnl Copyright (C) 2017 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_FUNC_REALLOCARRAY], +[ + dnl Persuade glibc to declare reallocarray(). + AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) + + AC_REQUIRE([gl_STDLIB_H_DEFAULTS]) + AC_CHECK_FUNCS([reallocarray]) + if test $ac_cv_func_reallocarray = no; then + HAVE_REALLOCARRAY=0 + fi +]) + +# Prerequisites of lib/reallocarray.c. +AC_DEFUN([gl_PREREQ_REALLOCARRAY], [:]) diff --git a/m4/stdlib_h.m4 b/m4/stdlib_h.m4 index 110fe2d1a..ec4a05815 100644 --- a/m4/stdlib_h.m4 +++ b/m4/stdlib_h.m4 @@ -21,9 +21,9 @@ AC_DEFUN([gl_STDLIB_H], #endif ]], [_Exit atoll canonicalize_file_name getloadavg getsubopt grantpt initstate initstate_r mkdtemp mkostemp mkostemps mkstemp mkstemps - posix_openpt ptsname ptsname_r qsort_r random random_r realpath rpmatch - secure_getenv setenv setstate setstate_r srandom srandom_r - strtod strtoll strtoull unlockpt unsetenv]) + posix_openpt ptsname ptsname_r qsort_r random random_r reallocarray + realpath rpmatch secure_getenv setenv setstate setstate_r srandom + srandom_r strtod strtoll strtoull unlockpt unsetenv]) ]) AC_DEFUN([gl_STDLIB_MODULE_INDICATOR], @@ -58,6 +58,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], GNULIB_QSORT_R=0; AC_SUBST([GNULIB_QSORT_R]) GNULIB_RANDOM=0; AC_SUBST([GNULIB_RANDOM]) GNULIB_RANDOM_R=0; AC_SUBST([GNULIB_RANDOM_R]) + GNULIB_REALLOCARRAY=0; AC_SUBST([GNULIB_REALLOCARRAY]) GNULIB_REALLOC_POSIX=0; AC_SUBST([GNULIB_REALLOC_POSIX]) GNULIB_REALPATH=0; AC_SUBST([GNULIB_REALPATH]) GNULIB_RPMATCH=0; AC_SUBST([GNULIB_RPMATCH]) @@ -89,6 +90,7 @@ AC_DEFUN([gl_STDLIB_H_DEFAULTS], HAVE_RANDOM=1; AC_SUBST([HAVE_RANDOM]) HAVE_RANDOM_H=1; AC_SUBST([HAVE_RANDOM_H]) HAVE_RANDOM_R=1; AC_SUBST([HAVE_RANDOM_R]) + HAVE_REALLOCARRAY=1; AC_SUBST([HAVE_REALLOCARRAY]) HAVE_REALPATH=1; AC_SUBST([HAVE_REALPATH]) HAVE_RPMATCH=1; AC_SUBST([HAVE_RPMATCH]) HAVE_SECURE_GETENV=1; AC_SUBST([HAVE_SECURE_GETENV]) diff --git a/modules/reallocarray b/modules/reallocarray new file mode 100644 index 000000000..f833d46dc --- /dev/null +++ b/modules/reallocarray @@ -0,0 +1,32 @@ +Description: +reallocarray() function that is glibc compatible. + +Files: +lib/reallocarray.c +m4/reallocarray.m4 + +Depends-on: +extensions +xalloc-oversized +realloc-gnu +stdlib + +configure.ac: +gl_FUNC_REALLOCARRAY +if test $HAVE_REALLOCARRAY = 0; then + AC_LIBOBJ([reallocarray]) + gl_PREREQ_REALLOCARRAY +fi +gl_MODULE_INDICATOR([reallocarray]) +gl_STDLIB_MODULE_INDICATOR([reallocarray]) + +Makefile.am: + +Include: + + +License: +GPLv3+ + +Maintainer: +all diff --git a/modules/reallocarray-tests b/modules/reallocarray-tests new file mode 100644 index 000000000..3943d7295 --- /dev/null +++ b/modules/reallocarray-tests @@ -0,0 +1,11 @@ +Files: +tests/test-reallocarray.c +tests/signature.h + +Depends-on: + +configure.ac: + +Makefile.am: +TESTS += test-reallocarray +check_PROGRAMS += test-reallocarray diff --git a/modules/stdlib b/modules/stdlib index 27b1caa3b..257b5dbd6 100644 --- a/modules/stdlib +++ b/modules/stdlib @@ -53,6 +53,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ -e 's/@''GNULIB_RANDOM''@/$(GNULIB_RANDOM)/g' \ -e 's/@''GNULIB_RANDOM_R''@/$(GNULIB_RANDOM_R)/g' \ -e 's/@''GNULIB_REALLOC_POSIX''@/$(GNULIB_REALLOC_POSIX)/g' \ + -e 's/@''GNULIB_REALLOCARRAY''@/$(GNULIB_REALLOCARRAY)/g' \ -e 's/@''GNULIB_REALPATH''@/$(GNULIB_REALPATH)/g' \ -e 's/@''GNULIB_RPMATCH''@/$(GNULIB_RPMATCH)/g' \ -e 's/@''GNULIB_SECURE_GETENV''@/$(GNULIB_SECURE_GETENV)/g' \ @@ -83,6 +84,7 @@ stdlib.h: stdlib.in.h $(top_builddir)/config.status $(CXXDEFS_H) \ -e 's|@''HAVE_RANDOM''@|$(HAVE_RANDOM)|g' \ -e 's|@''HAVE_RANDOM_H''@|$(HAVE_RANDOM_H)|g' \ -e 's|@''HAVE_RANDOM_R''@|$(HAVE_RANDOM_R)|g' \ + -e 's|@''HAVE_REALLOCARRAY''@|$(HAVE_REALLOCARRAY)|g' \ -e 's|@''HAVE_REALPATH''@|$(HAVE_REALPATH)|g' \ -e 's|@''HAVE_RPMATCH''@|$(HAVE_RPMATCH)|g' \ -e 's|@''HAVE_SECURE_GETENV''@|$(HAVE_SECURE_GETENV)|g' \ diff --git a/tests/test-reallocarray.c b/tests/test-reallocarray.c new file mode 100644 index 000000000..d81ab3ec0 --- /dev/null +++ b/tests/test-reallocarray.c @@ -0,0 +1,52 @@ +/* Test of reallocarray function. + Copyright (C) 2010-2017 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include + +#include "signature.h" +SIGNATURE_CHECK (reallocarray, void *, (void *, size_t, size_t)); + +/* Return 8. + Usual compilers are not able to infer something about the return value. */ +static unsigned int +eight (void) +{ + unsigned int x = rand (); + unsigned int y = x * x * x * x; + x++; y |= x * x * x * x; + x++; y |= x * x * x * x; + x++; y |= x * x * x * x; + y = y >> 1; + return y & -y; +} + +int +main () +{ + /* Check that reallocarray fails when requested to allocate a block of memory + larger than SIZE_MAX bytes. + We use eight (), not 8, to avoid a compiler warning from GCC 7. */ + char *p = reallocarray (NULL, (size_t) -1 / 8 + 1, eight ()); + if (p != NULL) + { + free (p); + return 1; + } + + return 0; +} -- 2.14.0