From fc962d4e7a7c3d799d9364d5427564c22ee3880c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Mon, 3 Jun 2013 12:31:46 +0300 Subject: [PATCH 1/2] mem: Add av_realloc_array and av_reallocp_array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These help avoiding overflows and simplify error handling. Signed-off-by: Martin Storsjö --- doc/APIchanges | 3 +++ libavutil/mem.c | 26 ++++++++++++++++++++++++++ libavutil/mem.h | 26 ++++++++++++++++++++++++++ libavutil/version.h | 2 +- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/doc/APIchanges b/doc/APIchanges index 0957f9e246..c3018357f8 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2012-10-22 API changes, most recent first: +2013-06-xx - xxxxxxx - lavu 52.13.0 - mem.h + Add av_realloc_array and av_reallocp_array + 2013-05-xx - xxxxxxx - lavfi 3.10.0 - avfilter.h Add support for slice multithreading to lavfi. Filters supporting threading are marked with AVFILTER_FLAG_SLICE_THREADS. diff --git a/libavutil/mem.c b/libavutil/mem.c index 391eb7db38..e901533cc7 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -136,6 +136,32 @@ void *av_realloc(void *ptr, size_t size) #endif } +void *av_realloc_array(void *ptr, size_t nmemb, size_t size) +{ + if (size <= 0 || nmemb >= INT_MAX / size) + return NULL; + return av_realloc(ptr, nmemb * size); +} + +int av_reallocp_array(void *ptr, size_t nmemb, size_t size) +{ + void **ptrptr = ptr; + void *ret; + if (size <= 0 || nmemb >= INT_MAX / size) + return AVERROR(ENOMEM); + if (nmemb <= 0) { + av_freep(ptr); + return 0; + } + ret = av_realloc(*ptrptr, nmemb * size); + if (!ret) { + av_freep(ptr); + return AVERROR(ENOMEM); + } + *ptrptr = ret; + return 0; +} + void av_free(void *ptr) { #if CONFIG_MEMALIGN_HACK diff --git a/libavutil/mem.h b/libavutil/mem.h index 8f4722447d..8a4fcd90ae 100644 --- a/libavutil/mem.h +++ b/libavutil/mem.h @@ -111,6 +111,32 @@ av_alloc_size(1, 2) static inline void *av_malloc_array(size_t nmemb, size_t siz */ void *av_realloc(void *ptr, size_t size) av_alloc_size(2); +/** + * Allocate or reallocate an array. + * If ptr is NULL and nmemb > 0, allocate a new block. If + * nmemb is zero, free the memory block pointed to by ptr. + * @param ptr Pointer to a memory block already allocated with + * av_malloc(z)() or av_realloc() or NULL. + * @param nmemb Number of elements + * @param size Size of the single element + * @return Pointer to a newly reallocated block or NULL if the block + * cannot be reallocated or the function is used to free the memory block. + */ +av_alloc_size(2, 3) void *av_realloc_array(void *ptr, size_t nmemb, size_t size); + +/** + * Allocate or reallocate an array. + * If *ptr is NULL and nmemb > 0, allocate a new block. If + * nmemb is zero, free the memory block pointed to by ptr. + * @param ptr Pointer to a pointer to a memory block already allocated + * with av_malloc(z)() or av_realloc(), or pointer to a pointer to NULL. + * The pointer is updated on success, or freed on failure. + * @param nmemb Number of elements + * @param size Size of the single element + * @return Zero on success, an AVERROR error code on failure. + */ +av_alloc_size(2, 3) int av_reallocp_array(void *ptr, size_t nmemb, size_t size); + /** * Free a memory block which has been allocated with av_malloc(z)() or * av_realloc(). diff --git a/libavutil/version.h b/libavutil/version.h index 9f0a976d9f..fa79e12a68 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -37,7 +37,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 52 -#define LIBAVUTIL_VERSION_MINOR 12 +#define LIBAVUTIL_VERSION_MINOR 13 #define LIBAVUTIL_VERSION_MICRO 0 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From 3b4feac1ec14f861bdd7f494f288f4d8dd7f449e Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sun, 2 Jun 2013 22:57:31 +0300 Subject: [PATCH 2/2] movenc: Keep track of the allocated size for the cluster array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When writing fragmented mp4, the cluster array is reset when a fragment is written. Instead of starting off reallocating the array only based on the number of current elements in it, keep track of how many elements there were allocated earlier. This avoids reallocating this array needlessly when writing fragmented mp4 files. Bug-Id: 525 Signed-off-by: Martin Storsjö --- libavformat/movenc.c | 10 ++++++---- libavformat/movenc.h | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 4ed99b7ea3..e2591681a5 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -2869,10 +2869,12 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) memcpy(trk->vos_data, pkt->data, size); } - if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) { - trk->cluster = av_realloc(trk->cluster, (trk->entry + MOV_INDEX_CLUSTER_SIZE) * sizeof(*trk->cluster)); - if (!trk->cluster) - return -1; + if (trk->entry >= trk->cluster_capacity) { + unsigned new_capacity = trk->entry + MOV_INDEX_CLUSTER_SIZE; + if (av_reallocp_array(&trk->cluster, new_capacity, + sizeof(*trk->cluster))) + return AVERROR(ENOMEM); + trk->cluster_capacity = new_capacity; } trk->cluster[trk->entry].pos = avio_tell(pb) - size; diff --git a/libavformat/movenc.h b/libavformat/movenc.h index 879c942a9f..2aa8ffb7e4 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -93,6 +93,7 @@ typedef struct MOVTrack { int vos_len; uint8_t *vos_data; MOVIentry *cluster; + unsigned cluster_capacity; int audio_vbr; int height; ///< active picture (w/o VBI) height for D-10/IMX uint32_t tref_tag;