summaryrefslogtreecommitdiff
path: root/lib/safe-alloc.h
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2021-04-18 20:50:55 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2021-04-18 20:59:52 -0700
commit5d5120d76b6e540c7e78332aa8302b3244b9ea02 (patch)
tree2b2fca5342515bc1c16c3e042aa27ea185f48580 /lib/safe-alloc.h
parent751b5840a02cd42c42d3aaf90640d4636c4271d2 (diff)
downloadgnulib-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.h91
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_ */