From 2050b5a87640328da73eda74cab5a9b2fb27d480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Wei=C3=9Fl?= Date: Sun, 27 Mar 2011 16:44:22 +0200 Subject: [PATCH] flac: fix segfault when playing corrupt flac files Each FLAC frame has it's own number of channels. If the number of channles is bigger than defined in STREAMINFO, cmus tries to access non-existing channels and segfaults. This patch not only fixes the segfault, but lets cmus decode the corrupt files. Solves Ubuntu Bug #635231 [1]. [1] https://bugs.launchpad.net/ubuntu/+source/cmus/+bug/635231 --- flac.c | 17 ++++++++++------- 1 files changed, 10 insertions(+), 7 deletions(-) diff --git a/flac.c b/flac.c index eec9e60..41dac45 100644 --- a/flac.c +++ b/flac.c @@ -187,7 +187,7 @@ static FLAC__StreamDecoderWriteStatus write_cb(const Dec *dec, const FLAC__Frame struct input_plugin_data *ip_data = data; struct flac_private *priv = ip_data->private; int frames, bytes, size, channels, bits, depth; - int ch, i, j = 0; + int ch, nch, i, j = 0; if (ip_data->sf == 0) { return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; @@ -213,47 +213,50 @@ static FLAC__StreamDecoderWriteStatus write_cb(const Dec *dec, const FLAC__Frame } depth = frame->header.bits_per_sample; + if (!depth) + depth = bits; + nch = frame->header.channels; if (depth == 8) { char *b = priv->buf + priv->buf_wpos; for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = buf[ch][i]; + b[j++] = buf[ch % nch][i]; } } else if (depth == 16) { int16_t *b = (int16_t *)(priv->buf + priv->buf_wpos); for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = LE16(buf[ch][i]); + b[j++] = LE16(buf[ch % nch][i]); } } else if (depth == 32) { int32_t *b = (int32_t *)(priv->buf + priv->buf_wpos); for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = LE32(buf[ch][i]); + b[j++] = LE32(buf[ch % nch][i]); } } else if (depth == 12) { /* -> 16 */ int16_t *b = (int16_t *)(priv->buf + priv->buf_wpos); for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = LE16(buf[ch][i] << 4); + b[j++] = LE16(buf[ch % nch][i] << 4); } } else if (depth == 20) { /* -> 32 */ int32_t *b = (int32_t *)(priv->buf + priv->buf_wpos); for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = LE32(buf[ch][i] << 12); + b[j++] = LE32(buf[ch % nch][i] << 12); } } else if (depth == 24) { /* -> 32 */ int32_t *b = (int32_t *)(priv->buf + priv->buf_wpos); for (i = 0; i < frames; i++) { for (ch = 0; ch < channels; ch++) - b[j++] = LE32(buf[ch][i] << 8); + b[j++] = LE32(buf[ch % nch][i] << 8); } } else { d_print("bits per sample changed to %d\n", depth); -- 1.7.4.1