aadec: improve eof detection

Remember the end position of audio content in the file and check it during
read_packet. There always seems to be other data beyond it, which could be
misinterpreted as more audio. Also add some extra avio_read error checks,
to bail early in case of a broken/truncated file.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Karsten Otto 2018-07-07 19:41:27 +02:00 committed by Michael Niedermayer
parent 3a2d21bc5f
commit c126065947
1 changed files with 13 additions and 2 deletions

View File

@ -46,6 +46,7 @@ typedef struct AADemuxContext {
struct AVTEA *tea_ctx; struct AVTEA *tea_ctx;
uint8_t file_key[16]; uint8_t file_key[16];
int64_t current_chapter_size; int64_t current_chapter_size;
int64_t content_end;
} AADemuxContext; } AADemuxContext;
static int get_second_size(char *codec_name) static int get_second_size(char *codec_name)
@ -197,6 +198,7 @@ static int aa_read_header(AVFormatContext *s)
} }
start = TOC[largest_idx].offset; start = TOC[largest_idx].offset;
avio_seek(pb, start, SEEK_SET); avio_seek(pb, start, SEEK_SET);
c->content_end = start + largest_size;
c->current_chapter_size = 0; c->current_chapter_size = 0;
return 0; return 0;
@ -214,6 +216,11 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
int ret; int ret;
AADemuxContext *c = s->priv_data; AADemuxContext *c = s->priv_data;
// are we at the end of the audio content?
if (avio_tell(s->pb) >= c->content_end) {
return AVERROR_EOF;
}
// are we at the start of a chapter? // are we at the start of a chapter?
if (c->current_chapter_size == 0) { if (c->current_chapter_size == 0) {
c->current_chapter_size = avio_rb32(s->pb); c->current_chapter_size = avio_rb32(s->pb);
@ -234,7 +241,9 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
// decrypt c->current_codec_second_size bytes // decrypt c->current_codec_second_size bytes
blocks = c->current_codec_second_size / TEA_BLOCK_SIZE; blocks = c->current_codec_second_size / TEA_BLOCK_SIZE;
for (i = 0; i < blocks; i++) { for (i = 0; i < blocks; i++) {
avio_read(s->pb, src, TEA_BLOCK_SIZE); ret = avio_read(s->pb, src, TEA_BLOCK_SIZE);
if (ret != TEA_BLOCK_SIZE)
return (ret < 0) ? ret : AVERROR_EOF;
av_tea_init(c->tea_ctx, c->file_key, 16); av_tea_init(c->tea_ctx, c->file_key, 16);
av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1); av_tea_crypt(c->tea_ctx, dst, src, 1, NULL, 1);
memcpy(buf + written, dst, TEA_BLOCK_SIZE); memcpy(buf + written, dst, TEA_BLOCK_SIZE);
@ -242,7 +251,9 @@ static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
} }
trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE; trailing_bytes = c->current_codec_second_size % TEA_BLOCK_SIZE;
if (trailing_bytes != 0) { // trailing bytes are left unencrypted! if (trailing_bytes != 0) { // trailing bytes are left unencrypted!
avio_read(s->pb, src, trailing_bytes); ret = avio_read(s->pb, src, trailing_bytes);
if (ret != trailing_bytes)
return (ret < 0) ? ret : AVERROR_EOF;
memcpy(buf + written, src, trailing_bytes); memcpy(buf + written, src, trailing_bytes);
written = written + trailing_bytes; written = written + trailing_bytes;
} }