aboutsummaryrefslogtreecommitdiffstats
path: root/src/crossfade.c
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 /src/crossfade.c
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().
Diffstat (limited to '')
-rw-r--r--src/crossfade.c20
1 files changed, 17 insertions, 3 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;
+ }
}