diff mbox series

[FFmpeg-devel,2/2] avformat/matroskaenc: Make ebml_num_size() more robust

Message ID 20200415210614.29152-2-andreas.rheinhardt@gmail.com
State Accepted
Headers show
Series [FFmpeg-devel,1/2] fftools/ffmpeg_opt: Check attachment filesize | expand


Context Check Description
andriy/default pending
andriy/make success Make finished
andriy/make_fate success Make fate finished

Commit Message

Andreas Rheinhardt April 15, 2020, 9:06 p.m. UTC
Matroska (or actually EBML) uses variable-length numbers where only
seven bits of every byte is usable for the length; the other bits encode
the length of the variable-length number. So in order to find out how
many bytes one needs to encode a given number one can use a loop like
while (num >> 7 * bytes) bytes++; the Matroska muxer effectively did this.

Yet it has a disadvantage: It is impossible for the result of a single
right shift of an unsigned number with most significant bit set to be
zero, because one can only shift by 0..(width - 1). On some
architectures like x64 it is not even possible to do it with undefined
right shifts in which case this leads to an infinite loop.

This can be easily avoided by switching to a loop whose condition is
(num >>= 7). The maximum value the so modified function can return
is 10; any value > 8 is invalid and will now lead to an assert in
put_ebml_num() or in start_ebml_master() (or actually in

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
One can run into this infinite loop by adding an attachment with
(int)size < 0 with ffmpeg on git master. If one applied this here
without the previous commit, one would run into a well-deserved assert.

 libavformat/matroskaenc.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
diff mbox series


diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index d3256d8f5d..407920172d 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -194,9 +194,11 @@  static void put_ebml_size_unknown(AVIOContext *pb, int bytes)
 static int ebml_num_size(uint64_t num)
-    int bytes = 1;
-    while ((num + 1) >> bytes * 7)
+    int bytes = 0;
+    num++;
+    do {
+    } while (num >>= 7);
     return bytes;