aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2008-09-29 17:25:08 +0200
committerMax Kellermann <max@duempel.org>2008-09-29 17:25:08 +0200
commitc85b570ad78a0185f45a08e63fefc667c4f056f7 (patch)
tree504cd571df6a1b58bfc717542700453e689f47e3
parent6e21e24caed1a9497e876e4b89b12687aa73d6ad (diff)
downloadmpd-c85b570ad78a0185f45a08e63fefc667c4f056f7.tar.gz
mpd-c85b570ad78a0185f45a08e63fefc667c4f056f7.tar.xz
mpd-c85b570ad78a0185f45a08e63fefc667c4f056f7.zip
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().
-rw-r--r--src/crossfade.c20
-rw-r--r--src/pcm_utils.c26
-rw-r--r--src/pcm_utils.h4
3 files changed, 28 insertions, 22 deletions
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,