summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2019-05-09 18:52:44 -0500
committerJason Ekstrand <[email protected]>2019-05-14 12:30:22 -0500
commit6c0f75c953e6640838d818b8f3603a56b0483f5d (patch)
tree2aff0d4c8ed0596eb00e4e07654751a64fe97dbb /src/util
parent621232694176ea83752505643b106c8d1c719893 (diff)
util/ralloc: Add helpers for growing zero-initialized memory
Unfortunately, we can't quite follow the standard C conventions for these because ralloc doesn't know the sizes of pointers. Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/util')
-rw-r--r--src/util/ralloc.c25
-rw-r--r--src/util/ralloc.h62
2 files changed, 87 insertions, 0 deletions
diff --git a/src/util/ralloc.c b/src/util/ralloc.c
index fc35661996d..0d20223d98f 100644
--- a/src/util/ralloc.c
+++ b/src/util/ralloc.c
@@ -198,6 +198,21 @@ reralloc_size(const void *ctx, void *ptr, size_t size)
}
void *
+rerzalloc_size(const void *ctx, void *ptr, size_t old_size, size_t new_size)
+{
+ if (unlikely(ptr == NULL))
+ return rzalloc_size(ctx, new_size);
+
+ assert(ralloc_parent(ptr) == ctx);
+ ptr = resize(ptr, new_size);
+
+ if (new_size > old_size)
+ memset((char *)ptr + old_size, 0, new_size - old_size);
+
+ return ptr;
+}
+
+void *
ralloc_array_size(const void *ctx, size_t size, unsigned count)
{
if (count > SIZE_MAX/size)
@@ -224,6 +239,16 @@ reralloc_array_size(const void *ctx, void *ptr, size_t size, unsigned count)
return reralloc_size(ctx, ptr, size * count);
}
+void *
+rerzalloc_array_size(const void *ctx, void *ptr, size_t size,
+ unsigned old_count, unsigned new_count)
+{
+ if (new_count > SIZE_MAX/size)
+ return NULL;
+
+ return rerzalloc_size(ctx, ptr, size * old_count, size * new_count);
+}
+
void
ralloc_free(void *ptr)
{
diff --git a/src/util/ralloc.h b/src/util/ralloc.h
index b4f372dfe9b..857ca5f797f 100644
--- a/src/util/ralloc.h
+++ b/src/util/ralloc.h
@@ -121,6 +121,23 @@ void *rzalloc_size(const void *ctx, size_t size) MALLOCLIKE;
*/
void *reralloc_size(const void *ctx, void *ptr, size_t size);
+/**
+ * Resize a ralloc-managed array, preserving data and initializing any newly
+ * allocated data to zero.
+ *
+ * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
+ * memory. Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0). This is different from talloc.
+ *
+ * \param ctx The context to use for new allocation. If \p ptr != NULL,
+ * it must be the same as ralloc_parent(\p ptr).
+ * \param ptr Pointer to the memory to be resized. May be NULL.
+ * \param old_size The amount of memory in the previous allocation, in bytes.
+ * \param new_size The amount of memory to allocate, in bytes.
+ */
+void *rerzalloc_size(const void *ctx, void *ptr,
+ size_t old_size, size_t new_size);
+
/// \defgroup array Array Allocators @{
/**
@@ -178,6 +195,28 @@ void *reralloc_size(const void *ctx, void *ptr, size_t size);
((type *) reralloc_array_size(ctx, ptr, sizeof(type), count))
/**
+ * \def rerzalloc(ctx, ptr, type, count)
+ * Resize a ralloc-managed array, preserving data and initializing any newly
+ * allocated data to zero.
+ *
+ * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
+ * memory. Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0). This is different from talloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count. This is necessary for security.
+ *
+ * \param ctx The context to use for new allocation. If \p ptr != NULL,
+ * it must be the same as ralloc_parent(\p ptr).
+ * \param ptr Pointer to the array to be resized. May be NULL.
+ * \param type The element type.
+ * \param old_count The number of elements in the previous allocation.
+ * \param new_count The number of elements to allocate.
+ */
+#define rerzalloc(ctx, ptr, type, old_count, new_count) \
+ ((type *) rerzalloc_array_size(ctx, ptr, sizeof(type), old_count, new_count))
+
+/**
* Allocate memory for an array chained off the given context.
*
* Similar to \c calloc, but does not initialize the memory to zero.
@@ -217,6 +256,29 @@ void *rzalloc_array_size(const void *ctx, size_t size, unsigned count) MALLOCLIK
*/
void *reralloc_array_size(const void *ctx, void *ptr, size_t size,
unsigned count);
+
+/**
+ * Resize a ralloc-managed array, preserving data and initializing any newly
+ * allocated data to zero.
+ *
+ * Similar to \c realloc. Unlike C89, passing 0 for \p size does not free the
+ * memory. Instead, it resizes it to a 0-byte ralloc context, just like
+ * calling ralloc_size(ctx, 0). This is different from talloc.
+ *
+ * More than a convenience function, this also checks for integer overflow when
+ * multiplying \c sizeof(type) and \p count. This is necessary for security.
+ *
+ * \param ctx The context to use for new allocation. If \p ptr != NULL,
+ * it must be the same as ralloc_parent(\p ptr).
+ * \param ptr Pointer to the array to be resized. May be NULL.
+ * \param size The size of an individual element.
+ * \param old_count The number of elements in the previous allocation.
+ * \param new_count The number of elements to allocate.
+ *
+ * \return True unless allocation failed.
+ */
+void *rerzalloc_array_size(const void *ctx, void *ptr, size_t size,
+ unsigned old_count, unsigned new_count);
/// @}
/**