ff_id3v2_read: add option to limit ID3 magic number search
Several chunked formats (AIFF, IFF,DSF) store ID3 metadata within an 'ID3 ' chunk tag. If such chunks are stored sequentially, it is possible for the ID3v2 parser to confuse the chunk tag for the ID3 magic number. e.g. [1st chunk tag ('ID3 ') | chunk size] [ID3 magic number | metadata ...] [2nd chunk tag ('ID3 ') | chunk size] [ID3 magic number | metadata ...] Fixes ticket #3530. Signed-off-by: Peter Ross <pross@xvid.org> Signed-off-by: Michael Niedermayer <michaelni@gmx.at> (cherry picked from commit 5331773cc33ba26b9e26ace643d926219e46a17b) Conflicts: libavformat/dsfdec.c
This commit is contained in:
parent
b45cd17d29
commit
30cf47c6f0
@ -237,7 +237,7 @@ static int aiff_read_header(AVFormatContext *s)
|
|||||||
break;
|
break;
|
||||||
case MKTAG('I', 'D', '3', ' '):
|
case MKTAG('I', 'D', '3', ' '):
|
||||||
position = avio_tell(pb);
|
position = avio_tell(pb);
|
||||||
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
|
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size);
|
||||||
if (id3v2_extra_meta)
|
if (id3v2_extra_meta)
|
||||||
if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) {
|
if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) {
|
||||||
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
|
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
|
||||||
|
@ -266,7 +266,7 @@ static void get_id3_tag(AVFormatContext *s, int len)
|
|||||||
{
|
{
|
||||||
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
|
ID3v2ExtraMeta *id3v2_extra_meta = NULL;
|
||||||
|
|
||||||
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
|
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, len);
|
||||||
if (id3v2_extra_meta)
|
if (id3v2_extra_meta)
|
||||||
ff_id3v2_parse_apic(s, &id3v2_extra_meta);
|
ff_id3v2_parse_apic(s, &id3v2_extra_meta);
|
||||||
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
|
ff_id3v2_free_extra_meta(&id3v2_extra_meta);
|
||||||
|
@ -878,16 +878,25 @@ error:
|
|||||||
|
|
||||||
static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata,
|
static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata,
|
||||||
AVFormatContext *s, const char *magic,
|
AVFormatContext *s, const char *magic,
|
||||||
ID3v2ExtraMeta **extra_meta)
|
ID3v2ExtraMeta **extra_meta, int64_t max_search_size)
|
||||||
{
|
{
|
||||||
int len, ret;
|
int len, ret;
|
||||||
uint8_t buf[ID3v2_HEADER_SIZE];
|
uint8_t buf[ID3v2_HEADER_SIZE];
|
||||||
int found_header;
|
int found_header;
|
||||||
int64_t off;
|
int64_t start, off;
|
||||||
|
|
||||||
|
if (max_search_size && max_search_size < ID3v2_HEADER_SIZE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
start = avio_tell(pb);
|
||||||
do {
|
do {
|
||||||
/* save the current offset in case there's nothing to read/skip */
|
/* save the current offset in case there's nothing to read/skip */
|
||||||
off = avio_tell(pb);
|
off = avio_tell(pb);
|
||||||
|
if (max_search_size && off - start >= max_search_size - ID3v2_HEADER_SIZE) {
|
||||||
|
avio_seek(pb, off, SEEK_SET);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
|
ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
|
||||||
if (ret != ID3v2_HEADER_SIZE) {
|
if (ret != ID3v2_HEADER_SIZE) {
|
||||||
avio_seek(pb, off, SEEK_SET);
|
avio_seek(pb, off, SEEK_SET);
|
||||||
@ -914,13 +923,13 @@ static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata,
|
|||||||
void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata,
|
void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata,
|
||||||
const char *magic, ID3v2ExtraMeta **extra_meta)
|
const char *magic, ID3v2ExtraMeta **extra_meta)
|
||||||
{
|
{
|
||||||
id3v2_read_internal(pb, metadata, NULL, magic, extra_meta);
|
id3v2_read_internal(pb, metadata, NULL, magic, extra_meta, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_id3v2_read(AVFormatContext *s, const char *magic,
|
void ff_id3v2_read(AVFormatContext *s, const char *magic,
|
||||||
ID3v2ExtraMeta **extra_meta)
|
ID3v2ExtraMeta **extra_meta, unsigned int max_search_size)
|
||||||
{
|
{
|
||||||
id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta);
|
id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta, max_search_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
|
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
|
||||||
|
@ -112,8 +112,10 @@ void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, const char *ma
|
|||||||
*
|
*
|
||||||
* @param extra_meta If not NULL, extra metadata is parsed into a list of
|
* @param extra_meta If not NULL, extra metadata is parsed into a list of
|
||||||
* ID3v2ExtraMeta structs and *extra_meta points to the head of the list
|
* ID3v2ExtraMeta structs and *extra_meta points to the head of the list
|
||||||
|
* @param[opt] max_search_search restrict ID3 magic number search (bytes from start)
|
||||||
*/
|
*/
|
||||||
void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta);
|
void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta,
|
||||||
|
unsigned int max_search_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize an ID3v2 tag.
|
* Initialize an ID3v2 tag.
|
||||||
|
@ -293,7 +293,7 @@ static int oma_read_header(AVFormatContext *s)
|
|||||||
ID3v2ExtraMeta *extra_meta = NULL;
|
ID3v2ExtraMeta *extra_meta = NULL;
|
||||||
OMAContext *oc = s->priv_data;
|
OMAContext *oc = s->priv_data;
|
||||||
|
|
||||||
ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta);
|
ff_id3v2_read(s, ID3v2_EA3_MAGIC, &extra_meta, 0);
|
||||||
ret = avio_read(s->pb, buf, EA3_HEADER_SIZE);
|
ret = avio_read(s->pb, buf, EA3_HEADER_SIZE);
|
||||||
if (ret < EA3_HEADER_SIZE)
|
if (ret < EA3_HEADER_SIZE)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -564,7 +564,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
|
|||||||
|
|
||||||
/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
|
/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
|
||||||
if (s->pb)
|
if (s->pb)
|
||||||
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
|
ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, 0);
|
||||||
|
|
||||||
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
|
if (!(s->flags&AVFMT_FLAG_PRIV_OPT) && s->iformat->read_header)
|
||||||
if ((ret = s->iformat->read_header(s)) < 0)
|
if ((ret = s->iformat->read_header(s)) < 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user