diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2021-04-18 20:50:55 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2021-04-18 20:59:52 -0700 |
commit | 5d5120d76b6e540c7e78332aa8302b3244b9ea02 (patch) | |
tree | 2b2fca5342515bc1c16c3e042aa27ea185f48580 /lib/safe-alloc.h | |
parent | 751b5840a02cd42c42d3aaf90640d4636c4271d2 (diff) | |
download | gnulib-5d5120d76b6e540c7e78332aa8302b3244b9ea02.tar.gz |
safe-alloc: fix pointer implementation
The old implementation assumed that all pointers use the same
internal representation, but the C standard doesn’t guarantee
this. Use void * (pointer) not void ** (pointer-to-pointer) for
the internal functions’ API. The internal functions now return
NULL if and only if they failed, and the macros translate that
into -1 or 0 to satisfy the existing API.
* doc/safe-alloc.texi (Safe Allocation Macros): Mention overflow.
* lib/safe-alloc.c: Major rewrite. Now this simply
defines SAFE_ALLOC_INLINE and includes safe-alloc.h.
* lib/safe-alloc.h: Include stddef.h, not stdlib.h.
(SAFE_ALLOC_INLINE): New macro; use Gnulib inline function style.
(safe_alloc_realloc_n): New API, which passes and returns
the pointer, and which returns NULL if and only if failure occurs.
(safe_alloc_check): New function.
(ALLOC, ALLOC_N, ALLOC_N_UNINITIALIZED, REALLOC_N):
Redo using the new API for internal functions, and using calloc
which is good enough since it’s GNU-compatible now.
(FREE): Expand to an expression rather than merely to something
that needs a following ‘;’ to become a statement.
* modules/safe-alloc (Depends-on): Add calloc-gnu.
Diffstat (limited to 'lib/safe-alloc.h')
-rw-r--r-- | lib/safe-alloc.h | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/lib/safe-alloc.h b/lib/safe-alloc.h index 1c655734ec..7de424f3c6 100644 --- a/lib/safe-alloc.h +++ b/lib/safe-alloc.h @@ -15,76 +15,89 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>. */ -/* Written by Daniel Berrange <berrange@redhat.com>, 2008 */ +/* Written by Daniel Berrange and Paul Eggert. */ #ifndef SAFE_ALLOC_H_ -# define SAFE_ALLOC_H_ +#define SAFE_ALLOC_H_ -# include <stdlib.h> +#include <stdlib.h> -/* Don't call these directly - use the macros below */ -int -safe_alloc_alloc_n (void *ptrptr, size_t size, size_t count, int zeroed) - _GL_ATTRIBUTE_NODISCARD; +#ifndef _GL_INLINE_HEADER_BEGIN + #error "Please include config.h first." +#endif +_GL_INLINE_HEADER_BEGIN +#ifndef SAFE_ALLOC_INLINE +# define SAFE_ALLOC_INLINE _GL_INLINE +#endif -int -safe_alloc_realloc_n (void *ptrptr, size_t size, size_t count) - _GL_ATTRIBUTE_NODISCARD; +/* Don't call these directly - use the macros below. */ +SAFE_ALLOC_INLINE void * +safe_alloc_realloc_n (void *ptr, size_t count, size_t size) +{ + if (count == 0 || size == 0) + count = size = 1; + return reallocarray (ptr, count, size); +} +SAFE_ALLOC_INLINE int _GL_ATTRIBUTE_NODISCARD +safe_alloc_check (void *ptr) +{ + /* Return 0 if the allocation was successful, -1 otherwise. */ + return -!ptr; +} /** * ALLOC: - * @ptr: pointer to hold address of allocated memory + * @ptr: pointer to allocated memory * - * Allocate sizeof(*ptr) bytes of memory and store - * the address of allocated memory in 'ptr'. Fill the + * Allocate sizeof *ptr bytes of memory and store + * the address of allocated memory in 'ptr'. Fill the * newly allocated memory with zeros. * - * Return -1 on failure to allocate, zero on success + * Return -1 on failure to allocate, zero on success. */ -# define ALLOC(ptr) \ - safe_alloc_alloc_n (&(ptr), sizeof (*(ptr)), 1, 1) +#define ALLOC(ptr) ALLOC_N (ptr, 1) /** * ALLOC_N: - * @ptr: pointer to hold address of allocated memory + * @ptr: pointer to allocated memory * @count: number of elements to allocate * - * Allocate an array of 'count' elements, each sizeof(*ptr) + * Allocate an array of 'count' elements, each sizeof *ptr * bytes long and store the address of allocated memory in - * 'ptr'. Fill the newly allocated memory with zeros. + * 'ptr'. Fill the newly allocated memory with zeros. * - * Return -1 on failure, 0 on success + * Return -1 on failure, 0 on success. */ -# define ALLOC_N(ptr, count) \ - safe_alloc_alloc_n (&(ptr), sizeof (*(ptr)), (count), 1) +#define ALLOC_N(ptr, count) \ + safe_alloc_check ((ptr) = calloc (count, sizeof *(ptr))) /** * ALLOC_N_UNINITIALIZED: - * @ptr: pointer to hold address of allocated memory + * @ptr: pointer to allocated memory * @count: number of elements to allocate * - * Allocate an array of 'count' elements, each sizeof(*ptr) + * Allocate an array of 'count' elements, each sizeof *ptr * bytes long and store the address of allocated memory in - * 'ptr'. Do not initialize the new memory at all. + * 'ptr'. Do not initialize the new memory at all. * - * Return -1 on failure to allocate, zero on success + * Return -1 on failure to allocate, zero on success. */ -# define ALLOC_N_UNINITIALIZED(ptr, count) \ - safe_alloc_alloc_n (&(ptr), sizeof (*(ptr)), (count), 0) +#define ALLOC_N_UNINITIALIZED(ptr, count) \ + safe_alloc_check ((ptr) = safe_alloc_realloc_n (NULL, count, sizeof *(ptr))) /** * REALLOC_N: - * @ptr: pointer to hold address of allocated memory + * @ptr: pointer to allocated memory * @count: number of elements to allocate * - * Re-allocate an array of 'count' elements, each sizeof(*ptr) + * Re-allocate an array of 'count' elements, each sizeof *ptr * bytes long and store the address of allocated memory in - * 'ptr'. Fill the newly allocated memory with zeros + * 'ptr'. Fill the newly allocated memory with zeros. * - * Return -1 on failure to reallocate, zero on success + * Return -1 on failure to reallocate, zero on success. */ -# define REALLOC_N(ptr, count) \ - safe_alloc_realloc_n (&(ptr), sizeof (*(ptr)), (count)) +#define REALLOC_N(ptr, count) \ + safe_alloc_check ((ptr) = safe_alloc_realloc_n (ptr, count, sizeof *(ptr))) /** * FREE: @@ -93,12 +106,8 @@ safe_alloc_realloc_n (void *ptrptr, size_t size, size_t count) * Free the memory stored in 'ptr' and update to point * to NULL. */ -# define FREE(ptr) \ - do \ - { \ - free (ptr); \ - (ptr) = NULL; \ - } \ - while (0) +#define FREE(ptr) ((void) (free (ptr), (ptr) = NULL)) + +_GL_INLINE_HEADER_END #endif /* SAFE_ALLOC_H_ */ |