[FFmpeg-devel] avformat/matroskadec: Check parents remaining length

Submitted by Michael Niedermayer on Feb. 13, 2019, 12:41 p.m.

Details

Message ID 20190213124131.25774-1-michael@niedermayer.cc
State New
Headers show

Commit Message

Michael Niedermayer Feb. 13, 2019, 12:41 p.m.
Reported-by: Steve Lhomme
This was found through the Hacker One program on VLC but is not a security issue in libavformat
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
---
 libavformat/matroskadec.c | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Comments

Michael Niedermayer Feb. 17, 2019, 8:45 a.m.
On Wed, Feb 13, 2019 at 01:41:31PM +0100, Michael Niedermayer wrote:
> Reported-by: Steve Lhomme
> This was found through the Hacker One program on VLC but is not a security issue in libavformat
> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
> ---
>  libavformat/matroskadec.c | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)

will apply an equivalent variant from steve

[...]

Patch hide | download patch | download mbox

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 4ad99db7db..4b10f44712 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -792,6 +792,19 @@  static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos)
     return AVERROR_EOF;
 }
 
+static int64_t ebml_parent_size_remaining(MatroskaDemuxContext *matroska)
+{
+    AVIOContext *pb = matroska->ctx->pb;
+    int64_t pos = avio_tell(pb);
+
+    if (matroska->num_levels > 0) {
+        MatroskaLevel *level = &matroska->levels[matroska->num_levels - 1];
+        if (level->length != (uint64_t)-1)
+            return level->length - (pos - level->start);
+    }
+    return INT64_MAX;
+}
+
 /*
  * Return: Whether we reached the end of a level in the hierarchy or not.
  */
@@ -1197,6 +1210,14 @@  static int ebml_parse_elem(MatroskaDemuxContext *matroska,
                    length, max_lengths[syntax->type], syntax->type);
             return AVERROR_INVALIDDATA;
         }
+
+        av_assert0(length <= INT64_MAX);
+        if  (ebml_parent_size_remaining(matroska) < (int64_t)length) {
+            av_log(matroska->ctx, AV_LOG_ERROR,
+                   "Invalid length 0x%"PRIx64" > 0x%"PRIx64" parent length\n",
+                   length, ebml_parent_size_remaining(matroska));
+            return AVERROR_INVALIDDATA;
+        }
     }
 
     switch (syntax->type) {