diff mbox

[FFmpeg-devel,v3,1/3] aadec: improve eof detection

Message ID 20180621165826.1714-2-ottoka@posteo.de
State Superseded
Headers show

Commit Message

Karsten Otto June 21, 2018, 4:58 p.m. UTC
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.
---
 libavformat/aadec.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

Comments

Michael Niedermayer July 2, 2018, 12:33 a.m. UTC | #1
On Thu, Jun 21, 2018 at 06:58:24PM +0200, Karsten Otto wrote:
> 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.

What is this additional data ?

[...]
Karsten Otto July 2, 2018, 6:25 a.m. UTC | #2
> Am 02.07.2018 um 02:33 schrieb Michael Niedermayer <michael@niedermayer.cc>:
> 
>> […]
> 
> What is this additional data ?
> 

Short answer: Since there is no official format specification, nobody really knows.

Longer answer: From what I have read, the aa format is a generic frame, containing several "tagged“ sections, where the first contains a metadata dictionary, and the largest section contains the encrypted audio. The current aadec.c code is working on this level. From personal experience with the official player I know the format usually contains a cover image; I guess this might be in one of the sections after the audio. If anybody ever finds out what these sections are good for and how to use them, that would be another patch series. I only know that it is not a good idea to try and play them, hence this fix to improve eof detection.

Cheers, Karsten
diff mbox

Patch

diff --git a/libavformat/aadec.c b/libavformat/aadec.c
index 8d39b1d9ba..4db71b1939 100644
--- a/libavformat/aadec.c
+++ b/libavformat/aadec.c
@@ -46,6 +46,7 @@  typedef struct AADemuxContext {
     struct AVTEA *tea_ctx;
     uint8_t file_key[16];
     int64_t current_chapter_size;
+    int64_t content_end;
 } AADemuxContext;
 
 static int get_second_size(char *codec_name)
@@ -197,6 +198,7 @@  static int aa_read_header(AVFormatContext *s)
     }
     start = TOC[largest_idx].offset;
     avio_seek(pb, start, SEEK_SET);
+    c->content_end = start + largest_size;
     c->current_chapter_size = 0;
 
     return 0;
@@ -214,6 +216,11 @@  static int aa_read_packet(AVFormatContext *s, AVPacket *pkt)
     int ret;
     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?
     if (c->current_chapter_size == 0) {
         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
     blocks = c->current_codec_second_size / TEA_BLOCK_SIZE;
     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_crypt(c->tea_ctx, dst, src, 1, NULL, 1);
         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;
     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);
         written = written + trailing_bytes;
     }