From 95e81df132e3dbc555974d125e56ae701a0f6968 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 26 Aug 2012 21:40:54 +0200 Subject: [PATCH] af_scaletempo: fix crash after channel reconfiguration af_scaletempo could crash if the audio format was changed with AF_CONTROL_REINIT while the filter was active. In a test case this happened when audio channels were reconfigured from 6 channels to 2 and playback speed was set to 2. The problem is that reinitialization does not properly reset filter state. Thus the amount of buffered audio can be larger than the new maximum buffer size, i.e. the invariant bytes_queued <= bytes_queue is violated. As a result, memcpy is called with a negative size. Fix this by resetting the buffer length when reconfiguring (set the bytes_queued variable to 0). Also reset some other state for clarity and robustness, although these changes aren't strictly needed for avoiding the actual crash. This may also get rid of some noise played after reinitialization, caused by using the old buffer contents which were now in the wrong audio format. --- libaf/af_scaletempo.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libaf/af_scaletempo.c b/libaf/af_scaletempo.c index 4ea25bf9e361..7b951860d404 100644 --- a/libaf/af_scaletempo.c +++ b/libaf/af_scaletempo.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "af.h" #include "libavutil/common.h" @@ -104,6 +105,7 @@ static int fill_queue(struct af_instance_s* af, af_data_t* data, int offset) if (bytes_in > 0) { int bytes_copy = FFMIN(s->bytes_queue - s->bytes_queued, bytes_in); + assert(bytes_copy >= 0); memcpy(s->buf_queue + s->bytes_queued, (int8_t*)data->audio + offset, bytes_copy); @@ -331,6 +333,7 @@ static int control(struct af_instance_s* af, int cmd, void* arg) s->bytes_standing = s->bytes_stride; s->samples_standing = s->bytes_standing / bps; s->output_overlap = NULL; + s->bytes_overlap = 0; } else { s->samples_overlap = frames_overlap * nch; s->bytes_overlap = frames_overlap * nch * bps; @@ -419,6 +422,9 @@ static int control(struct af_instance_s* af, int cmd, void* arg) return AF_ERROR; } + s->bytes_queued = 0; + s->bytes_to_slide = 0; + mp_msg (MSGT_AFILTER, MSGL_DBG2, "[scaletempo] " "%.2f stride_in, %i stride_out, %i standing, " "%i overlap, %i search, %i queue, %s mode\n",