Hi,

 After trying some fuzzing on libavcodec, it seems that a lot of decoders
does not check (or not enough) for buffer overread which can lead for some
to a segfault.

 I attached a patch that make get_bits.h function checked for overread by
default but let safe decoders disabling the checks at compilation time by
defining UNCHECK_BITSTREAM_READER before including get_bits.h.
 If such patch would be including, I would gladly provide a patch
adding the #define UNCHECK_BITSTREAM_READER to the decoder that are 'safe'.

I haven't yet benchmark the performance loss but will do so.

 One decoder breaks with this patch: mpegaudio. It seems to do weird things
with two get bit context and switching them while decoding. I will try to
have a look at it (unless someone would volunteer to explain me what it is
doing :)

Also, I haven't implemented the checks for A32_BITSTREAM_READER. But I am not
sure when (or even if) this reader is used.

Regards,

-- 
fenrir

>From 51abf83451b1f17283035c5b0742df1d01a09394 Mon Sep 17 00:00:00 2001
From: Laurent Aimar <fen...@videolan.org>
Date: Fri, 9 Sep 2011 00:52:36 +0200
Subject: [PATCH] Prevent by default for overread in get_bits.h functions.

It can be disabled (at compilation time so without any performance loss)
for decoder that check for overreads by themselves by defining
UNCHECK_BITSTREAM_READER before including get_bits.h

Checks for A32_BITSTREAM_READER are not yet implemented.
---
 libavcodec/get_bits.h |   27 ++++++++++++++++++++++++++-
 1 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index d2ae345..e3fedb9 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -35,6 +35,9 @@
 #include "libavutil/log.h"
 #include "mathops.h"
 
+/* You can define UNCHECK_BITSTREAM_READER before including this file to
+ * avoid the penalty cost of checking for overread */
+
 #if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER)
 #   define ALT_BITSTREAM_READER
 #endif
@@ -127,6 +130,7 @@ for examples see get_bits, show_bits, skip_bits, get_vlc
 
 #   define OPEN_READER(name, gb)                \
     unsigned int name##_index = (gb)->index;    \
+    unsigned int av_unused name##_size_in_bits = (gb)->size_in_bits;    \
     unsigned int av_unused name##_cache = 0
 
 #   define CLOSE_READER(name, gb) (gb)->index = name##_index
@@ -144,7 +148,15 @@ for examples see get_bits, show_bits, skip_bits, get_vlc
 # endif
 
 // FIXME name?
-#   define SKIP_COUNTER(name, gb, num) name##_index += (num)
+#ifndef UNCHECK_BITSTREAM_READER
+#   define SKIP_COUNTER(name, gb, num) do {     \
+        name##_index += (num);                  \
+        if (name##_index > name##_size_in_bits) \
+            name##_index = name##_size_in_bits; \
+    } while (0)
+#else
+#   define SKIP_COUNTER(name, gb, num) name##_index += (num);
+#endif
 
 #   define SKIP_BITS(name, gb, num) do {        \
         SKIP_CACHE(name, gb, num);              \
@@ -172,10 +184,18 @@ static inline int get_bits_count(const GetBitContext *s){
 
 static inline void skip_bits_long(GetBitContext *s, int n){
     s->index += n;
+#ifndef UNCHECK_BITSTREAM_READER
+    if (s->index > s->size_in_bits)
+        s->index = s->size_in_bits;
+#endif
 }
 
 #elif defined A32_BITSTREAM_READER
 
+#ifndef UNCHECK_BITSTREAM_READER
+#   warn "Checked bistream reader unimplemented"
+#endif
+
 #   define MIN_CACHE_BITS 32
 
 #   define OPEN_READER(name, gb)                        \
@@ -311,7 +331,12 @@ static inline unsigned int get_bits1(GetBitContext *s){
     result <<= index & 7;
     result >>= 8 - 1;
 #endif
+#ifndef UNCHECK_BITSTREAM_READER
+    if (index < s->size_in_bits)
+        index++;
+#else
     index++;
+#endif
     s->index = index;
 
     return result;
-- 
1.7.2.5

_______________________________________________
libav-devel mailing list
libav-devel@libav.org
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to