player: Recover from AAC decoding error

Decoding errors are usually not fatal, so we can recover by skipping
the broken frame. This also fixes invalid memory reads caused by
sampleSizeCurr >= sampleSizeN.

(upstream git commit dd6c620b53272e2eb4b091a835cd250309f04cad)
This commit is contained in:
dcoppa 2012-10-30 16:59:23 +00:00
parent 392934d98e
commit 6e08287364
2 changed files with 76 additions and 2 deletions

View File

@ -1,11 +1,11 @@
# $OpenBSD: Makefile,v 1.46 2012/09/23 10:18:21 dcoppa Exp $
# $OpenBSD: Makefile,v 1.47 2012/10/30 16:59:23 dcoppa Exp $
SHARED_ONLY = Yes
COMMENT = console client for pandora
DISTNAME = pianobar-2012.09.07
REVISION = 0
REVISION = 1
EXTRACT_SUFX = .tar.bz2
CATEGORIES = audio

View File

@ -0,0 +1,74 @@
$OpenBSD: patch-src_player_c,v 1.13 2012/10/30 16:59:23 dcoppa Exp $
commit dd6c620b53272e2eb4b091a835cd250309f04cad
Author: Lars-Dominik Braun <lars@6xq.net>
Date: Sun Oct 28 18:24:50 2012 +0100
player: Recover from AAC decoding error
Decoding errors are usually not fatal, so we can recover by skipping the
broken frame. This also fixes invalid memory reads caused by
sampleSizeCurr >= sampleSizeN. See issue #304.
--- src/player.c.orig Tue Oct 30 17:45:04 2012
+++ src/player.c Tue Oct 30 17:45:34 2012
@@ -28,6 +28,7 @@ THE SOFTWARE.
#include <math.h>
#include <stdint.h>
#include <limits.h>
+#include <assert.h>
#include <arpa/inet.h>
#include "player.h"
@@ -135,17 +136,31 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, s
NeAACDecFrameInfo frameInfo;
size_t i;
- while ((player->bufferFilled - player->bufferRead) >
- player->sampleSize[player->sampleSizeCurr]) {
+ while (player->sampleSizeCurr < player->sampleSizeN &&
+ (player->bufferFilled - player->bufferRead) >=
+ player->sampleSize[player->sampleSizeCurr]) {
+ /* going through this loop can take up to a few seconds =>
+ * allow earlier thread abort */
+ QUIT_PAUSE_CHECK;
+
/* decode frame */
aacDecoded = NeAACDecDecode(player->aacHandle, &frameInfo,
- player->buffer + player->bufferRead,
+ &player->buffer[player->bufferRead],
player->sampleSize[player->sampleSizeCurr]);
+ player->bufferRead += player->sampleSize[player->sampleSizeCurr];
+ ++player->sampleSizeCurr;
+
if (frameInfo.error != 0) {
+ /* skip this frame, songPlayed will be slightly off if this
+ * happens */
BarUiMsg (player->settings, MSG_ERR, "Decoding error: %s\n",
NeAACDecGetErrorMessage (frameInfo.error));
- break;
+ continue;
}
+ /* assuming data in stsz atom is correct */
+ assert (frameInfo.bytesconsumed ==
+ player->sampleSize[player->sampleSizeCurr-1]);
+
for (i = 0; i < frameInfo.samples; i++) {
aacDecoded[i] = applyReplayGain (aacDecoded[i], player->scale);
}
@@ -157,11 +172,10 @@ static WaitressCbReturn_t BarPlayerAACCb (void *ptr, s
(unsigned long long int) BAR_PLAYER_MS_TO_S_FACTOR /
(unsigned long long int) player->samplerate /
(unsigned long long int) player->channels;
- player->bufferRead += frameInfo.bytesconsumed;
- player->sampleSizeCurr++;
- /* going through this loop can take up to a few seconds =>
- * allow earlier thread abort */
- QUIT_PAUSE_CHECK;
+ }
+ if (player->sampleSizeCurr >= player->sampleSizeN) {
+ /* no more frames, drop data */
+ player->bufferRead = player->bufferFilled;
}
} else {
if (player->mode == PLAYER_INITIALIZED) {