[FFmpeg-devel] Fix mjpeg decoder runaway from internal buffer

Michael Niedermayer michaelni
Thu Oct 21 01:13:43 CEST 2010


On Wed, Oct 20, 2010 at 07:36:51PM +0400, Anatoly Nenashev wrote:
> On 19.10.2010 19:14, Michael Niedermayer wrote:
>> On Tue, Oct 19, 2010 at 06:50:21PM +0400, Anatoly Nenashev wrote:
>>    
>>> On 19.10.2010 18:31, Michael Niedermayer wrote:
>>>      
>>>> On Tue, Oct 19, 2010 at 05:51:55PM +0400, Anatoliy Nenashev wrote:
>>>>
>>>>        
>>>>> Hi!
>>>>> In some cases there is a situation when mjpeg decoder runaway from
>>>>> allocated s->buffer.
>>>>> Usually it happens in VLC decoder for DC-AC coefficients when input
>>>>> frame is cirrupted.
>>>>> In this case it is caused by "specific" garbage at the end of the memory
>>>>> allocated for s->buffer.
>>>>>
>>>>> Here is a fix to prevent this situation.
>>>>>
>>>>>          
>>>> i dont see how this would prevent overreading the buffer. And no i dont
>>>> care that on your computer with your sample this week it works.
>>>> unless you can show that this always works (which i doubt) its not
>>>> a correct solution.
>>>>
>>>>        
>>> 0xFF  value aligned to byte is deprecated for VLC value because it is
>>> used for markers. Thats why VLC decoder will  stop within error  when
>>> intersects s->buffer_size position.
>>>      
>> what you write makes no sense. any VLC is allowed, 0xFF occuring
>> in the bitstream are explicitly escaped. If i missed something in the
>> jpeg spec that disallows such vlcs then please refer to this part of the spec
>>    
> You are right. Sorry, it was my mistake in specification reading.
> I found another way to fix original problem. I have added new macro in  
> get_bits.h to check up if the buffer overreaded.
> This macro is used in mjpeg decoder. It also may be used in other decoders.
>
>

>  get_bits.h |   24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)
> 1915f32b1baadab644335e3137c93c05ad3814ac  getbits.patch
> diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h
> index f4b3646..398e0f8 100644
> --- a/libavcodec/get_bits.h
> +++ b/libavcodec/get_bits.h
> @@ -124,6 +124,12 @@ LAST_SKIP_CACHE(name, gb, num)
>  LAST_SKIP_BITS(name, gb, num)
>      is equivalent to LAST_SKIP_CACHE; SKIP_COUNTER
>  
> +INIT_OVERREAD_CHECKER(name,gb)
> +    initialize local variables for overread checker
> +
> +BUFFER_OVERREADED(name,gb)
> +    check if buffer overreaded
> +
>  for examples see get_bits, show_bits, skip_bits, get_vlc
>  */
>  
> @@ -181,6 +187,12 @@ for examples see get_bits, show_bits, skip_bits, get_vlc
>  #   define GET_CACHE(name, gb)\
>          ((uint32_t)name##_cache)
>  
> +#   define INIT_OVERREAD_CHECKER(name, gb)\
> +    const int name##_size_in_bits= (gb)->size_in_bits;\
> +
> +#   define BUFFER_OVERREADED(name, gb)\
> +        (name##_index >= name##_size_in_bits)
> +
>  static inline int get_bits_count(const GetBitContext *s){
>      return s->index;
>  }
> @@ -235,6 +247,12 @@ static inline void skip_bits_long(GetBitContext *s, int n){
>  #   define GET_CACHE(name, gb)\
>          ((uint32_t)name##_cache)
>  
> +#   define INIT_OVERREAD_CHECKER(name, gb)\
> +    const uint8_t * name##_buffer_end= (gb)->buffer_end;\
> +
> +#   define BUFFER_OVERREADED(name, gb)\
> +        (name##_buffer_ptr > name##_buffer_end + 1)
> +
>  static inline int get_bits_count(const GetBitContext *s){
>      return (s->buffer_ptr - s->buffer)*8 - 16 + s->bit_count;
>  }
> @@ -310,6 +328,12 @@ static inline void skip_bits_long(GetBitContext *s, int n){
>  #   define GET_CACHE(name, gb)\
>          (name##_cache0)
>  
> +#   define INIT_OVERREAD_CHECKER(name, gb)\
> +    const uint32_t * name##_buffer_end= (gb)->buffer_end;\
> +
> +#   define BUFFER_OVERREADED(name, gb)\
> +        (name##_buffer_ptr > name##_buffer_end + 1)
> +
>  static inline int get_bits_count(const GetBitContext *s){
>      return ((uint8_t*)s->buffer_ptr - s->buffer)*8 - 32 + s->bit_count;
>  }

>  mjpegdec.c |   17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 207d3a410e151e1e30ddaddde51449846e111c51  mjpegdec.patch
> diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c
> index 5686380..04f2dfe 100644
> --- a/libavcodec/mjpegdec.c
> +++ b/libavcodec/mjpegdec.c
> @@ -407,6 +407,7 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
>      /* AC coefs */
>      i = 0;
>      {OPEN_READER(re, &s->gb)
> +     INIT_OVERREAD_CHECKER(re, &s->gb)
>      for(;;) {
>          UPDATE_CACHE(re, &s->gb);
>          GET_VLC(code, re, &s->gb, s->vlcs[1][ac_index].table, 9, 2)
> @@ -440,6 +441,11 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block,
>              j = s->scantable.permutated[i];
>              block[j] = level * quant_matrix[j];
>          }
> +
> +        if (BUFFER_OVERREADED(re, &s->gb)) {
> +            av_log(s->avctx, AV_LOG_ERROR, "buffer overreaded in decode_block\n");
> +            return -1;
> +        }
>      }
>      CLOSE_READER(re, &s->gb)}
>

checking after each coefficient is too slow.
Finding out how many bits a block can contain in worst case allocating
that amount extra and then just checking once a block is simpler.
This also should then not require these macros

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

The real ebay dictionary, page 3
"Rare item" - "Common item with rare defect or maybe just a lie"
"Professional" - "'Toy' made in china, not functional except as doorstop"
"Experts will know" - "The seller hopes you are not an expert"
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20101021/318ccaef/attachment.pgp>



More information about the ffmpeg-devel mailing list