From 3fa539c4e2c03d0db082424be1743def87c75543 Mon Sep 17 00:00:00 2001 From: mplayer-svn Date: Mon, 13 Feb 2012 19:33:48 +0000 Subject: [PATCH] demux_audio: do not decode ID3v2 tag data as audio data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Minor simplification. Part of patch by Benoît Thébaudeau [benoit thebaudeau () advansee com]. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@34718 b3059339-0415-0410-9bf9-f77b7e298cf2 Detect ID3v2 tag at the end of the file and stop demuxing before its start. Avoids trying to decode its data as MP3. Patch by Benoît Thébaudeau [benoit thebaudeau {} advansee com]. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@34719 b3059339-0415-0410-9bf9-f77b7e298cf2 Author: reimar --- libmpdemux/demux_audio.c | 63 +++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/libmpdemux/demux_audio.c b/libmpdemux/demux_audio.c index 9dbb89ce0f..e73af17e5f 100644 --- a/libmpdemux/demux_audio.c +++ b/libmpdemux/demux_audio.c @@ -320,6 +320,34 @@ static unsigned int mp3_vbr_frames(stream_t *s, off_t off) { return 0; } +/** + * @brief Determine the total size of an ID3v2 tag. + * + * @param maj_ver major version of the ID3v2 tag + * @param s stream to be read, assumed to be positioned at revision byte + * + * @return 0 (error or malformed tag) or tag size + */ +static unsigned int id3v2_tag_size(uint8_t maj_ver, stream_t *s) { + unsigned int header_footer_size; + unsigned int size; + int i; + + if(stream_read_char(s) == 0xff) + return 0; + header_footer_size = ((stream_read_char(s) & 0x10) && maj_ver >= 4) ? 20 : 10; + + size = 0; + for(i = 0; i < 4; i++) { + uint8_t data = stream_read_char(s); + if (data & 0x80) + return 0; + size = size << 7 | data; + } + + return header_footer_size + size; +} + static int demux_audio_open(demuxer_t* demuxer) { stream_t *s; sh_audio_t* sh_audio; @@ -353,12 +381,10 @@ static int demux_audio_open(demuxer_t* demuxer) { // We found wav header. Now we can have 'fmt ' or a mp3 header // empty the buffer step = 4; - } else if( hdr[0] == 'I' && hdr[1] == 'D' && hdr[2] == '3' && (hdr[3] >= 2)) { - int len; - stream_skip(s,2); - stream_read(s,hdr,4); - len = (hdr[0]<<21) | (hdr[1]<<14) | (hdr[2]<<7) | hdr[3]; - stream_skip(s,len); + } else if( hdr[0] == 'I' && hdr[1] == 'D' && hdr[2] == '3' && hdr[3] >= 2 && hdr[3] != 0xff) { + unsigned int len = id3v2_tag_size(hdr[3], s); + if(len > 0) + stream_skip(s,len-10); step = 4; } else if( found_WAVE && hdr[0] == 'f' && hdr[1] == 'm' && hdr[2] == 't' && hdr[3] == ' ' ) { frmt = WAV; @@ -412,11 +438,9 @@ static int demux_audio_open(demuxer_t* demuxer) { free(mp3_found); mp3_found = NULL; if(s->end_pos && (s->flags & MP_STREAM_SEEK) == MP_STREAM_SEEK) { - char tag[4]; stream_seek(s,s->end_pos-128); - stream_read(s,tag,3); - tag[3] = '\0'; - if(!strcmp(tag,"TAG")) { + stream_read(s,hdr,3); + if(!memcmp(hdr,"TAG",3)) { char buf[31]; uint8_t g; demuxer->movi_end = stream_tell(s)-3; @@ -443,6 +467,25 @@ static int demux_audio_open(demuxer_t* demuxer) { g = stream_read_char(s); demux_info_add(demuxer,"Genre",genres[g]); } + stream_seek(s,demuxer->movi_end-10); + stream_read(s,hdr,4); + if(!memcmp(hdr,"3DI",3) && hdr[3] >= 4 && hdr[3] != 0xff) { + unsigned int len = id3v2_tag_size(hdr[3], s); + if(len > 0) { + if(len > demuxer->movi_end - demuxer->movi_start) { + mp_msg(MSGT_DEMUX,MSGL_WARN,"Audio demuxer: bad ID3v2 tag size: larger than stream (%u).\n",len); + len = FFMIN(10,demuxer->movi_end-demuxer->movi_start); + } else { + stream_seek(s,demuxer->movi_end-len); + stream_read(s,hdr,4); + if(memcmp(hdr,"ID3",3) || hdr[3] < 4 || hdr[3] == 0xff || id3v2_tag_size(hdr[3], s) != len) { + mp_msg(MSGT_DEMUX,MSGL_WARN,"Audio demuxer: damaged appended ID3v2 tag detected.\n"); + len = FFMIN(10,demuxer->movi_end-demuxer->movi_start); + } + } + demuxer->movi_end -= len; + } + } } if (duration && demuxer->movi_end && demuxer->movi_end > demuxer->movi_start) sh_audio->wf->nAvgBytesPerSec = (demuxer->movi_end - demuxer->movi_start) / duration; sh_audio->i_bps = sh_audio->wf->nAvgBytesPerSec;