From 48e11c6fe0dc55752af7d17d316ba408e2565d1c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Tue, 3 Oct 2023 20:38:11 +0200 Subject: [PATCH] audioconvert: handle realloc errors The original pointer is untouched when realloc fails and returns NULL so make sure we free the previous values. --- spa/plugins/audioconvert/audioconvert.c | 67 +++++++++++++++++++------ 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/spa/plugins/audioconvert/audioconvert.c b/spa/plugins/audioconvert/audioconvert.c index 1427260c3..2cf15d26c 100644 --- a/spa/plugins/audioconvert/audioconvert.c +++ b/spa/plugins/audioconvert/audioconvert.c @@ -2445,6 +2445,53 @@ static inline void dequeue_buffer(struct impl *this, struct port *port, struct b SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_QUEUED); } +static void free_tmp(struct impl *this) +{ + uint32_t i; + + spa_log_warn(this->log, "free tmp %d", this->empty_size); + + free(this->empty); + this->empty = NULL; + this->empty_size = 0; + free(this->scratch); + this->scratch = NULL; + free(this->tmp[0]); + this->tmp[0] = NULL; + free(this->tmp[1]); + this->tmp[1] = NULL; + for (i = 0; i < MAX_PORTS; i++) { + this->tmp_datas[0][i] = NULL; + this->tmp_datas[1][i] = NULL; + } +} + +static int ensure_tmp(struct impl *this, uint32_t maxsize) +{ + if (maxsize > this->empty_size) { + float *empty, *scratch, *tmp[2]; + + spa_log_warn(this->log, "resize tmp %d -> %d", this->empty_size, maxsize); + + if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL) + this->empty = empty; + if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL) + this->scratch = scratch; + if ((tmp[0] = realloc(this->tmp[0], (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL) + this->tmp[0] = tmp[0]; + if ((tmp[1] = realloc(this->tmp[1], (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL) + this->tmp[1] = tmp[1]; + + if (empty == NULL || scratch == NULL || tmp[0] == NULL || tmp[1] == NULL) { + free_tmp(this); + return -ENOMEM; + } + memset(this->empty, 0, maxsize + MAX_ALIGN); + this->empty_size = maxsize; + } + return 0; +} + static int impl_node_port_use_buffers(void *object, enum spa_direction direction, @@ -2456,6 +2503,7 @@ impl_node_port_use_buffers(void *object, struct impl *this = object; struct port *port; uint32_t i, j, maxsize; + int res; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -2512,17 +2560,9 @@ impl_node_port_use_buffers(void *object, if (direction == SPA_DIRECTION_OUTPUT) queue_buffer(this, port, i); } - if (maxsize > this->empty_size) { - this->empty = realloc(this->empty, maxsize + MAX_ALIGN); - this->scratch = realloc(this->scratch, maxsize + MAX_ALIGN); - this->tmp[0] = realloc(this->tmp[0], (maxsize + MAX_ALIGN) * MAX_PORTS); - this->tmp[1] = realloc(this->tmp[1], (maxsize + MAX_ALIGN) * MAX_PORTS); - if (this->empty == NULL || this->scratch == NULL || - this->tmp[0] == NULL || this->tmp[1] == NULL) - return -errno; - memset(this->empty, 0, maxsize + MAX_ALIGN); - this->empty_size = maxsize; - } + if ((res = ensure_tmp(this, maxsize)) < 0) + return res; + port->n_buffers = n_buffers; return 0; @@ -3250,10 +3290,7 @@ static int impl_clear(struct spa_handle *handle) free_dir(&this->dir[SPA_DIRECTION_INPUT]); free_dir(&this->dir[SPA_DIRECTION_OUTPUT]); - free(this->empty); - free(this->scratch); - free(this->tmp[0]); - free(this->tmp[1]); + free_tmp(this); if (this->resample.free) resample_free(&this->resample);