Add avifCalloc() and harden allocation call sites
Introduce avifCalloc() as a centralized overflow-checked,
zero-initializing allocation helper and convert existing open-coded
allocation patterns to use it.
This change replaces repeated patterns of:
p = avifAlloc(...);
memset(p, 0, ...);
with a single reusable helper that performs allocation arithmetic
validation and zero-initialization in one place.diff --git a/include/avif/internal.h b/include/avif/internal.h
index cdaa654..e109496 100644
--- a/include/avif/internal.h
+++ b/include/avif/internal.h
@@ -81,6 +81,13 @@
#define AVIF_CONTENT_TYPE_XMP "application/rdf+xml"
// ---------------------------------------------------------------------------
+// Memory management
+
+// Allocates count * size bytes and zero-initializes them. Returns NULL on memory
+// allocation failure, including the case when count * size overflows size_t.
+void * avifCalloc(size_t count, size_t size);
+
+// ---------------------------------------------------------------------------
// Utils
float avifRoundf(float v);
diff --git a/src/avif.c b/src/avif.c
index f44dc49..e4bbfa1 100644
--- a/src/avif.c
+++ b/src/avif.c
@@ -234,9 +234,8 @@
dstImage->numProperties = 0;
if (srcImage->numProperties != 0) {
- dstImage->properties = (avifImageItemProperty *)avifAlloc(srcImage->numProperties * sizeof(srcImage->properties[0]));
+ dstImage->properties = (avifImageItemProperty *)avifCalloc(srcImage->numProperties, sizeof(srcImage->properties[0]));
AVIF_CHECKERR(dstImage->properties != NULL, AVIF_RESULT_OUT_OF_MEMORY);
- memset(dstImage->properties, 0, srcImage->numProperties * sizeof(srcImage->properties[0]));
dstImage->numProperties = srcImage->numProperties;
for (size_t i = 0; i < srcImage->numProperties; ++i) {
memcpy(dstImage->properties[i].boxtype, srcImage->properties[i].boxtype, sizeof(srcImage->properties[i].boxtype));
diff --git a/src/codec_aom.c b/src/codec_aom.c
index bc6bd55..beba54e 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -1395,11 +1395,10 @@
avifCodec * avifCodecCreateAOM(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
#if defined(AVIF_CODEC_AOM_DECODE)
codec->getNextImage = aomCodecGetNextImage;
@@ -1411,12 +1410,11 @@
#endif
codec->destroyInternal = aomCodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(struct avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
return codec;
}
diff --git a/src/codec_avm.c b/src/codec_avm.c
index 2328d6e..6222f7f 100644
--- a/src/codec_avm.c
+++ b/src/codec_avm.c
@@ -1043,11 +1043,10 @@
avifCodec * avifCodecCreateAVM(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
codec->getNextImage = avmCodecGetNextImage;
@@ -1055,11 +1054,10 @@
codec->encodeFinish = avmCodecEncodeFinish;
codec->destroyInternal = avmCodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(struct avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
return codec;
}
diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c
index 3f83c35..2f1210a 100644
--- a/src/codec_dav1d.c
+++ b/src/codec_dav1d.c
@@ -232,19 +232,17 @@
avifCodec * avifCodecCreateDav1d(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
codec->getNextImage = dav1dCodecGetNextImage;
codec->destroyInternal = dav1dCodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(struct avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
return codec;
}
diff --git a/src/codec_libgav1.c b/src/codec_libgav1.c
index 7d07adf..ec791cc 100644
--- a/src/codec_libgav1.c
+++ b/src/codec_libgav1.c
@@ -140,20 +140,18 @@
avifCodec * avifCodecCreateGav1(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
codec->getNextImage = gav1CodecGetNextImage;
codec->destroyInternal = gav1CodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(struct avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
Libgav1DecoderSettingsInitDefault(&codec->internal->gav1Settings);
return codec;
}
diff --git a/src/codec_rav1e.c b/src/codec_rav1e.c
index dc220ed..97c92be 100644
--- a/src/codec_rav1e.c
+++ b/src/codec_rav1e.c
@@ -333,20 +333,18 @@
avifCodec * avifCodecCreateRav1e(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
codec->encodeImage = rav1eCodecEncodeImage;
codec->encodeFinish = rav1eCodecEncodeFinish;
codec->destroyInternal = rav1eCodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(struct avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(struct avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
return codec;
}
diff --git a/src/codec_svt.c b/src/codec_svt.c
index 2b887e8..a76fb5b 100644
--- a/src/codec_svt.c
+++ b/src/codec_svt.c
@@ -291,11 +291,10 @@
if (uvSize * 2 > UINT32_MAX - input_buffer->n_filled_len) {
goto cleanup;
}
- uvPlanes = avifAlloc(uvSize);
+ uvPlanes = avifCalloc(uvSize, sizeof(uint8_t));
if (uvPlanes == NULL) {
goto cleanup;
}
- memset(uvPlanes, 0, uvSize);
input_picture_buffer->cb = uvPlanes;
input_buffer->n_filled_len += (uint32_t)uvSize;
input_picture_buffer->cr = uvPlanes;
@@ -402,21 +401,19 @@
avifCodec * avifCodecCreateSvt(void)
{
- avifCodec * codec = (avifCodec *)avifAlloc(sizeof(avifCodec));
+ avifCodec * codec = (avifCodec *)avifCalloc(1, sizeof(avifCodec));
if (codec == NULL) {
return NULL;
}
- memset(codec, 0, sizeof(struct avifCodec));
codec->encodeImage = svtCodecEncodeImage;
codec->encodeFinish = svtCodecEncodeFinish;
codec->destroyInternal = svtCodecDestroyInternal;
- codec->internal = (struct avifCodecInternal *)avifAlloc(sizeof(avifCodecInternal));
+ codec->internal = (struct avifCodecInternal *)avifCalloc(1, sizeof(avifCodecInternal));
if (codec->internal == NULL) {
avifFree(codec);
return NULL;
}
- memset(codec->internal, 0, sizeof(struct avifCodecInternal));
return codec;
}
@@ -426,11 +423,10 @@
if (!(*input_buf)) {
return AVIF_FALSE;
}
- (*input_buf)->p_buffer = avifAlloc(sizeof(EbSvtIOFormat));
+ (*input_buf)->p_buffer = avifCalloc(1, sizeof(EbSvtIOFormat));
if (!(*input_buf)->p_buffer) {
return AVIF_FALSE;
}
- memset((*input_buf)->p_buffer, 0, sizeof(EbSvtIOFormat));
(*input_buf)->size = sizeof(EbBufferHeaderType);
(*input_buf)->p_app_private = NULL;
(*input_buf)->pic_type = EB_AV1_INVALID_PICTURE;
diff --git a/src/gainmap.c b/src/gainmap.c
index b35734f..d87f96a 100644
--- a/src/gainmap.c
+++ b/src/gainmap.c
@@ -393,11 +393,10 @@
const int maxNumBuckets = 10000;
const int numBuckets = AVIF_MIN((int)ceilf((max - min) / bucketSize), maxNumBuckets);
- int * histogram = avifAlloc(sizeof(int) * numBuckets);
+ int * histogram = avifCalloc(numBuckets, sizeof(int));
if (histogram == NULL) {
return AVIF_RESULT_OUT_OF_MEMORY;
}
- memset(histogram, 0, sizeof(int) * numBuckets);
for (size_t i = 0; i < numPixels; ++i) {
++(histogram[avifValueToBucketIdx(gainMapF[i], min, max, numBuckets)]);
}
diff --git a/src/io.c b/src/io.c
index 08eb032..bd0ebda 100644
--- a/src/io.c
+++ b/src/io.c
@@ -132,11 +132,10 @@
avifIO * avifIOCreateMemoryReader(const uint8_t * data, size_t size)
{
- avifIOMemoryReader * reader = (avifIOMemoryReader *)avifAlloc(sizeof(avifIOMemoryReader));
+ avifIOMemoryReader * reader = (avifIOMemoryReader *)avifCalloc(1, sizeof(avifIOMemoryReader));
if (reader == NULL) {
return NULL;
}
- memset(reader, 0, sizeof(avifIOMemoryReader));
reader->io.destroy = avifIOMemoryReaderDestroy;
reader->io.read = avifIOMemoryReaderRead;
reader->io.sizeHint = size;
@@ -230,12 +229,11 @@
return NULL;
}
- avifIOFileReader * reader = (avifIOFileReader *)avifAlloc(sizeof(avifIOFileReader));
+ avifIOFileReader * reader = (avifIOFileReader *)avifCalloc(1, sizeof(avifIOFileReader));
if (!reader) {
fclose(f);
return NULL;
}
- memset(reader, 0, sizeof(avifIOFileReader));
reader->f = f;
reader->io.destroy = avifIOFileReaderDestroy;
reader->io.read = avifIOFileReaderRead;
diff --git a/src/mem.c b/src/mem.c
index 54d9495..46f9fb5 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -1,7 +1,7 @@
// Copyright 2019 Joe Drago. All rights reserved.
// SPDX-License-Identifier: BSD-2-Clause
-#include "avif/avif.h"
+#include "avif/internal.h"
#include <stdlib.h>
@@ -17,6 +17,11 @@
return malloc(size);
}
+void * avifCalloc(size_t count, size_t size)
+{
+ return calloc(count, size);
+}
+
void avifFree(void * p)
{
free(p);