diff options
Diffstat (limited to 'libavformat/wavenc.c')
-rw-r--r-- | libavformat/wavenc.c | 53 |
1 files changed, 29 insertions, 24 deletions
diff --git a/libavformat/wavenc.c b/libavformat/wavenc.c index 078b7fcd9a..563a30d005 100644 --- a/libavformat/wavenc.c +++ b/libavformat/wavenc.c @@ -50,8 +50,6 @@ #define RF64_NEVER 0 #define RF64_ALWAYS 1 -#define PEAK_BUFFER_SIZE 1024 - typedef enum { PEAK_OFF = 0, PEAK_ON, @@ -72,8 +70,9 @@ typedef struct WAVMuxContext { int64_t maxpts; int16_t *peak_maxpos, *peak_maxneg; uint32_t peak_num_frames; - uint32_t peak_outbuf_size; + unsigned peak_outbuf_size; uint32_t peak_outbuf_bytes; + unsigned size_increment; uint8_t *peak_output; int last_duration; int write_bext; @@ -171,15 +170,15 @@ static av_cold int peak_init_writer(AVFormatContext *s) "Writing 16 bit peak for 8 bit audio does not make sense\n"); return AVERROR(EINVAL); } + if (par->channels > INT_MAX / (wav->peak_bps * wav->peak_ppv)) + return AVERROR(ERANGE); + wav->size_increment = par->channels * wav->peak_bps * wav->peak_ppv; wav->peak_maxpos = av_mallocz_array(par->channels, sizeof(*wav->peak_maxpos)); wav->peak_maxneg = av_mallocz_array(par->channels, sizeof(*wav->peak_maxneg)); - wav->peak_output = av_malloc(PEAK_BUFFER_SIZE); - if (!wav->peak_maxpos || !wav->peak_maxneg || !wav->peak_output) + if (!wav->peak_maxpos || !wav->peak_maxneg) goto nomem; - wav->peak_outbuf_size = PEAK_BUFFER_SIZE; - return 0; nomem: @@ -187,14 +186,24 @@ nomem: return AVERROR(ENOMEM); } -static void peak_write_frame(AVFormatContext *s) +static int peak_write_frame(AVFormatContext *s) { WAVMuxContext *wav = s->priv_data; AVCodecParameters *par = s->streams[0]->codecpar; + unsigned new_size = wav->peak_outbuf_bytes + wav->size_increment; + uint8_t *tmp; int c; - if (!wav->peak_output) - return; + if (new_size > INT_MAX) { + wav->write_peak = PEAK_OFF; + return AVERROR(ERANGE); + } + tmp = av_fast_realloc(wav->peak_output, &wav->peak_outbuf_size, new_size); + if (!tmp) { + wav->write_peak = PEAK_OFF; + return AVERROR(ENOMEM); + } + wav->peak_output = tmp; for (c = 0; c < par->channels; c++) { wav->peak_maxneg[c] = -wav->peak_maxneg[c]; @@ -208,17 +217,6 @@ static void peak_write_frame(AVFormatContext *s) wav->peak_maxpos[c] = FFMAX(wav->peak_maxpos[c], wav->peak_maxneg[c]); - if (wav->peak_outbuf_size - wav->peak_outbuf_bytes < - wav->peak_format * wav->peak_ppv) { - wav->peak_outbuf_size += PEAK_BUFFER_SIZE; - wav->peak_output = av_realloc(wav->peak_output, - wav->peak_outbuf_size); - if (!wav->peak_output) { - av_log(s, AV_LOG_ERROR, "No memory for peak data\n"); - return; - } - } - if (wav->peak_format == PEAK_FORMAT_UINT8) { wav->peak_output[wav->peak_outbuf_bytes++] = wav->peak_maxpos[c]; @@ -240,6 +238,8 @@ static void peak_write_frame(AVFormatContext *s) wav->peak_maxneg[c] = 0; } wav->peak_num_frames++; + + return 0; } static int peak_write_chunk(AVFormatContext *s) @@ -253,8 +253,11 @@ static int peak_write_chunk(AVFormatContext *s) char timestamp[28]; /* Peak frame of incomplete block at end */ - if (wav->peak_block_pos) - peak_write_frame(s); + if (wav->peak_block_pos) { + int ret = peak_write_frame(s); + if (ret < 0) + return ret; + } memset(timestamp, 0, sizeof(timestamp)); if (!(s->flags & AVFMT_FLAG_BITEXACT)) { @@ -384,7 +387,9 @@ static int wav_write_packet(AVFormatContext *s, AVPacket *pkt) if (++c == s->streams[0]->codecpar->channels) { c = 0; if (++wav->peak_block_pos == wav->peak_block_size) { - peak_write_frame(s); + int ret = peak_write_frame(s); + if (ret < 0) + return ret; wav->peak_block_pos = 0; } } |