Commit 782e64fb authored by Anton Khirnov's avatar Anton Khirnov

wv,mpc8: don't return apetag data in packets.

parent 9c9c21ea
...@@ -113,40 +113,47 @@ static int ape_tag_read_field(AVFormatContext *s) ...@@ -113,40 +113,47 @@ static int ape_tag_read_field(AVFormatContext *s)
return 0; return 0;
} }
void ff_ape_parse_tag(AVFormatContext *s) int64_t ff_ape_parse_tag(AVFormatContext *s)
{ {
AVIOContext *pb = s->pb; AVIOContext *pb = s->pb;
int file_size = avio_size(pb); int file_size = avio_size(pb);
uint32_t val, fields, tag_bytes; uint32_t val, fields, tag_bytes;
uint8_t buf[8]; uint8_t buf[8];
int64_t tag_start;
int i; int i;
if (file_size < APE_TAG_FOOTER_BYTES) if (file_size < APE_TAG_FOOTER_BYTES)
return; return 0;
avio_seek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET); avio_seek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);
avio_read(pb, buf, 8); /* APETAGEX */ avio_read(pb, buf, 8); /* APETAGEX */
if (strncmp(buf, "APETAGEX", 8)) { if (strncmp(buf, "APETAGEX", 8)) {
return; return 0;
} }
val = avio_rl32(pb); /* APE tag version */ val = avio_rl32(pb); /* APE tag version */
if (val > APE_TAG_VERSION) { if (val > APE_TAG_VERSION) {
av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION); av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=%d)\n", APE_TAG_VERSION);
return; return 0;
} }
tag_bytes = avio_rl32(pb); /* tag size */ tag_bytes = avio_rl32(pb); /* tag size */
if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) { if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {
av_log(s, AV_LOG_ERROR, "Tag size is way too big\n"); av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");
return; return 0;
}
tag_start = file_size - tag_bytes - APE_TAG_FOOTER_BYTES;
if (tag_start < 0) {
av_log(s, AV_LOG_ERROR, "Invalid tag size %u.\n", tag_bytes);
return 0;
} }
fields = avio_rl32(pb); /* number of fields */ fields = avio_rl32(pb); /* number of fields */
if (fields > 65536) { if (fields > 65536) {
av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields); av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);
return; return 0;
} }
val = avio_rl32(pb); /* flags */ val = avio_rl32(pb); /* flags */
...@@ -159,4 +166,6 @@ void ff_ape_parse_tag(AVFormatContext *s) ...@@ -159,4 +166,6 @@ void ff_ape_parse_tag(AVFormatContext *s)
for (i=0; i<fields; i++) for (i=0; i<fields; i++)
if (ape_tag_read_field(s) < 0) break; if (ape_tag_read_field(s) < 0) break;
return tag_start;
} }
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
/** /**
* Read and parse an APE tag * Read and parse an APE tag
*
* @return offset of the tag start in the file
*/ */
void ff_ape_parse_tag(AVFormatContext *s); int64_t ff_ape_parse_tag(AVFormatContext *s);
#endif /* AVFORMAT_APETAG_H */ #endif /* AVFORMAT_APETAG_H */
...@@ -52,6 +52,8 @@ typedef struct { ...@@ -52,6 +52,8 @@ typedef struct {
int frame; int frame;
int64_t header_pos; int64_t header_pos;
int64_t samples; int64_t samples;
int64_t apetag_start;
} MPCContext; } MPCContext;
static inline int64_t bs_get_v(uint8_t **bs) static inline int64_t bs_get_v(uint8_t **bs)
...@@ -243,7 +245,7 @@ static int mpc8_read_header(AVFormatContext *s) ...@@ -243,7 +245,7 @@ static int mpc8_read_header(AVFormatContext *s)
if (pb->seekable) { if (pb->seekable) {
int64_t pos = avio_tell(s->pb); int64_t pos = avio_tell(s->pb);
ff_ape_parse_tag(s); c->apetag_start = ff_ape_parse_tag(s);
avio_seek(s->pb, pos, SEEK_SET); avio_seek(s->pb, pos, SEEK_SET);
} }
...@@ -258,6 +260,11 @@ static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -258,6 +260,11 @@ static int mpc8_read_packet(AVFormatContext *s, AVPacket *pkt)
while(!s->pb->eof_reached){ while(!s->pb->eof_reached){
pos = avio_tell(s->pb); pos = avio_tell(s->pb);
/* don't return bogus packets with the ape tag data */
if (c->apetag_start && pos >= c->apetag_start)
return AVERROR_EOF;
mpc8_get_chunk_header(s->pb, &tag, &size); mpc8_get_chunk_header(s->pb, &tag, &size);
if (size < 0) if (size < 0)
return -1; return -1;
......
...@@ -64,6 +64,8 @@ typedef struct { ...@@ -64,6 +64,8 @@ typedef struct {
int block_parsed; int block_parsed;
uint8_t extra[WV_EXTRA_SIZE]; uint8_t extra[WV_EXTRA_SIZE];
int64_t pos; int64_t pos;
int64_t apetag_start;
} WVContext; } WVContext;
static int wv_probe(AVProbeData *p) static int wv_probe(AVProbeData *p)
...@@ -88,6 +90,11 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, ...@@ -88,6 +90,11 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb,
uint32_t chmask; uint32_t chmask;
wc->pos = avio_tell(pb); wc->pos = avio_tell(pb);
/* don't return bogus packets with the ape tag data */
if (wc->apetag_start && wc->pos >= wc->apetag_start)
return AVERROR_EOF;
if (!append) { if (!append) {
tag = avio_rl32(pb); tag = avio_rl32(pb);
if (tag != MKTAG('w', 'v', 'p', 'k')) if (tag != MKTAG('w', 'v', 'p', 'k'))
...@@ -252,7 +259,7 @@ static int wv_read_header(AVFormatContext *s) ...@@ -252,7 +259,7 @@ static int wv_read_header(AVFormatContext *s)
if (s->pb->seekable) { if (s->pb->seekable) {
int64_t cur = avio_tell(s->pb); int64_t cur = avio_tell(s->pb);
ff_ape_parse_tag(s); wc->apetag_start = ff_ape_parse_tag(s);
if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX))
ff_id3v1_read(s); ff_id3v1_read(s);
avio_seek(s->pb, cur, SEEK_SET); avio_seek(s->pb, cur, SEEK_SET);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment