Hi,

On Fri, Sep 09, 2011 at 08:16:31AM +0200, Laurent Aimar wrote:
> On Fri, Sep 09, 2011 at 02:26:53AM +0200, Michael Niedermayer wrote:
> > On Fri, Sep 09, 2011 at 02:05:19AM +0200, Laurent Aimar wrote:
> > [...]
> > > > > @@ -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
> > > > 
> > > > i think this will break error detection of some files with some
> > > > decoders because they detect it by an overread having happened
> > > > 
> > > > also it might lead to infinite loops or other unexpected things
> > > > as some decoders depend on them
> > > > hitting zero padding after the buffer which is guranteed to lead to
> > > > vlc decoding failures for them as they have no valid all 0 vlc code
> > >  I see. A simple way could be to simply add 8 * PADDING_SIZE to the check.
> > > I will add that locally.
> > 
> > Iam not sure this is enough
> > the problematic case iam thinking of is a decoder that works with
> > slices, so the guranteed 0 padding would be farther away if the
> > current slice is not the last. mpeg1/2 should be examples of this
> > case
> > 
> > maybe just returning 0 after size+something would work better
>  I wanted to avoid the check while loading the cache, but you're right,
> it's probably the simplest solution to avoid the issue you mentionned.
>  I will provide a patch to do that instead.

 New patch attached and it's a bit simpler.

 Now out of bound index is checked when reading the data and the value 0 is
returned in such cases. get_bits_count() will then return the real number
of bits read.

 I still have an issue with mpegaudio though. I will try to fix it first and
then I will do some benchmarks.

Regards,

-- 
fenrir
>From af1e5c3a989291a1e78b1f0dbeabf76f5e8bdfc6 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
UNCHECKED_BITSTREAM_READER before including get_bits.h

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

diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
index d2ae345..687169b 100644
--- a/libavcodec/get_bits.h
+++ b/libavcodec/get_bits.h
@@ -35,6 +35,8 @@
 #include "libavutil/log.h"
 #include "mathops.h"
 
+/* You can define UNCHECKED_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,18 +129,37 @@ 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
 
 # ifdef ALT_BITSTREAM_READER_LE
-#   define UPDATE_CACHE(name, gb) \
-    name##_cache = AV_RL32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) >> (name##_index&0x07)
+#   ifdef UNCHECKED_BITSTREAM_READER
+#       define UPDATE_CACHE(name, gb) \
+            name##_cache = AV_RL32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) >> (name##_index&0x07)
+#   else
+#       define UPDATE_CACHE(name, gb) do { \
+            if (name##_index < name##_size_in_bits) \
+                name##_cache = AV_RL32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) >> (name##_index&0x07); \
+            else \
+                name##_cache = 0; \
+        } while (0)
+#   endif
 
 #   define SKIP_CACHE(name, gb, num) name##_cache >>= (num)
 # else
-#   define UPDATE_CACHE(name, gb) \
-    name##_cache = AV_RB32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) << (name##_index&0x07)
+#   ifdef UNCHECKED_BITSTREAM_READER
+#       define UPDATE_CACHE(name, gb) \
+            name##_cache = AV_RB32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) << (name##_index&0x07)
+#   else
+#       define UPDATE_CACHE(name, gb) do {\
+            if (name##_index < name##_size_in_bits) \
+                name##_cache = AV_RB32(((const uint8_t *)(gb)->buffer)+(name##_index>>3)) << (name##_index&0x07); \
+            else \
+                name##_cache = 0; \
+        } while (0)
+#   endif
 
 #   define SKIP_CACHE(name, gb, num) name##_cache <<= (num)
 # endif
@@ -303,7 +324,12 @@ static inline void skip_bits(GetBitContext *s, int n){
 static inline unsigned int get_bits1(GetBitContext *s){
 #ifdef ALT_BITSTREAM_READER
     unsigned int index = s->index;
+#ifdef UNCHECKED_BITSTREAM_READER
     uint8_t result = s->buffer[index>>3];
+#else
+    uint8_t result = index < s->size_in_bits ? s->buffer[index>>3] : 0;
+#endif
+
 #ifdef ALT_BITSTREAM_READER_LE
     result >>= index & 7;
     result &= 1;
-- 
1.7.2.5

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

Reply via email to