From c85b570ad78a0185f45a08e63fefc667c4f056f7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 29 Sep 2008 17:25:08 +0200 Subject: pcm_utils: pass only one buffer size to pcm_mix() pcm_mix() might overflow the destination buffer if it is smaller than the second buffer. This is ok because the physical buffer size passed by cross_fade_apply() is always big enough, but clutters pcm_mix() with complicated length checks and contains a dangerous buffer overflow pitfall. Simplify pcm_mix()/pcm_add() and pass only the smaller buffer size; let cross_fade_apply() do the memcpy(). --- src/crossfade.c | 20 +++++++++++++++++--- src/pcm_utils.c | 26 +++++++++----------------- src/pcm_utils.h | 4 ++-- 3 files changed, 28 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/crossfade.c b/src/crossfade.c index b99b9f7f0..c4a26fa6b 100644 --- a/src/crossfade.c +++ b/src/crossfade.c @@ -49,14 +49,28 @@ void cross_fade_apply(ob_chunk * a, const ob_chunk * b, const struct audio_format *format, unsigned int current_chunk, unsigned int num_chunks) { + size_t size; + assert(current_chunk <= num_chunks); + size = b->chunkSize > a->chunkSize + ? a->chunkSize + : b->chunkSize; + pcm_mix(a->data, b->data, - a->chunkSize, - b->chunkSize, + size, format, ((float)current_chunk) / num_chunks); - if (b->chunkSize > a->chunkSize) + + if (b->chunkSize > a->chunkSize) { + /* the second buffer is larger than the first one: + there is unmixed rest at the end. Copy it over. + The output buffer API guarantees that there is + enough room in a->data. */ + memcpy(a->data + a->chunkSize, + b->data + a->chunkSize, + b->chunkSize - a->chunkSize); a->chunkSize = b->chunkSize; + } } diff --git a/src/pcm_utils.c b/src/pcm_utils.c index ee0c94d45..6e7156aea 100644 --- a/src/pcm_utils.c +++ b/src/pcm_utils.c @@ -90,8 +90,8 @@ void pcm_volumeChange(char *buffer, int bufferSize, } } -static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, - size_t bufferSize2, int vol1, int vol2, +static void pcm_add(char *buffer1, const char *buffer2, size_t size, + int vol1, int vol2, const struct audio_format *format) { int32_t temp32; @@ -102,7 +102,7 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, switch (format->bits) { case 16: - while (bufferSize1 > 0 && bufferSize2 > 0) { + while (size > 0) { temp32 = (vol1 * (*buffer16_1) + vol2 * (*buffer16_2)); @@ -112,14 +112,11 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, *buffer16_1 = pcm_range(temp32, 16); buffer16_1++; buffer16_2++; - bufferSize1 -= 2; - bufferSize2 -= 2; + size -= 2; } - if (bufferSize2 > 0) - memcpy(buffer16_1, buffer16_2, bufferSize2); break; case 8: - while (bufferSize1 > 0 && bufferSize2 > 0) { + while (size > 0) { temp32 = (vol1 * (*buffer8_1) + vol2 * (*buffer8_2)); temp32 += pcm_dither(); @@ -128,20 +125,16 @@ static void pcm_add(char *buffer1, const char *buffer2, size_t bufferSize1, *buffer8_1 = pcm_range(temp32, 8); buffer8_1++; buffer8_2++; - bufferSize1--; - bufferSize2--; + size--; } - if (bufferSize2 > 0) - memcpy(buffer8_1, buffer8_2, bufferSize2); break; default: FATAL("%i bits not supported by pcm_add!\n", format->bits); } } -void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, - size_t bufferSize2, const struct audio_format *format, - float portion1) +void pcm_mix(char *buffer1, const char *buffer2, size_t size, + const struct audio_format *format, float portion1) { int vol1; float s = sin(M_PI_2 * portion1); @@ -150,8 +143,7 @@ void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, vol1 = s * 1000 + 0.5; vol1 = vol1 > 1000 ? 1000 : (vol1 < 0 ? 0 : vol1); - pcm_add(buffer1, buffer2, bufferSize1, bufferSize2, vol1, 1000 - vol1, - format); + pcm_add(buffer1, buffer2, size, vol1, 1000 - vol1, format); } #ifdef HAVE_LIBSAMPLERATE diff --git a/src/pcm_utils.h b/src/pcm_utils.h index d3dfcaf2d..59ced1331 100644 --- a/src/pcm_utils.h +++ b/src/pcm_utils.h @@ -47,8 +47,8 @@ typedef struct _ConvState { void pcm_volumeChange(char *buffer, int bufferSize, const struct audio_format *format, int volume); -void pcm_mix(char *buffer1, const char *buffer2, size_t bufferSize1, - size_t bufferSize2, const struct audio_format *format, float portion1); +void pcm_mix(char *buffer1, const char *buffer2, size_t size, + const struct audio_format *format, float portion1); size_t pcm_convertAudioFormat(const struct audio_format *inFormat, const char *inBuffer, size_t inSize, -- cgit v1.2.3