From 0ecca7a49f8e254c12a3a1de048d738bfbb614c6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 12 Jan 2005 00:16:25 +0000 Subject: various security fixes and precautionary checks Originally committed as revision 3822 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/4xm.c | 24 ++++++++++---- libavcodec/asv1.c | 8 ++++- libavcodec/avcodec.h | 9 ++++- libavcodec/dv.c | 4 ++- libavcodec/ffv1.c | 18 ++++++++-- libavcodec/flicvideo.c | 2 +- libavcodec/h263.c | 2 +- libavcodec/h263dec.c | 9 +++-- libavcodec/h264.c | 4 +++ libavcodec/huffyuv.c | 85 +++++++++++++++++++++++++++++++++--------------- libavcodec/imgconvert.c | 8 ++++- libavcodec/imgresample.c | 2 ++ libavcodec/indeo3.c | 4 +++ libavcodec/mem.c | 8 +++++ libavcodec/mjpeg.c | 21 ++++++++++-- libavcodec/mpegvideo.c | 37 ++++++++++++++++----- libavcodec/mpegvideo.h | 4 ++- libavcodec/png.c | 11 +++++-- libavcodec/pnm.c | 15 +++++++-- libavcodec/ratecontrol.c | 2 ++ libavcodec/snow.c | 15 +++++++-- libavcodec/svq1.c | 13 ++++++-- libavcodec/utils.c | 34 +++++++++++++++++-- libavcodec/vp3.c | 8 +++++ libavcodec/vqavideo.c | 4 +++ libavcodec/xan.c | 3 ++ 26 files changed, 285 insertions(+), 69 deletions(-) (limited to 'libavcodec') diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 9f82fb1c04..5cc5f575f0 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -323,13 +323,19 @@ static int decode_p_frame(FourXContext *f, uint8_t *buf, int length){ uint16_t *src= (uint16_t*)f->last_picture.data[0]; uint16_t *dst= (uint16_t*)f->current_picture.data[0]; const int stride= f->current_picture.linesize[0]>>1; - const int bitstream_size= get32(buf+8); - const int bytestream_size= get32(buf+16); - const int wordstream_size= get32(buf+12); + const unsigned int bitstream_size= get32(buf+8); + const unsigned int bytestream_size= get32(buf+16); + const unsigned int wordstream_size= get32(buf+12); - if(bitstream_size+ bytestream_size+ wordstream_size + 20 != length) + if(bitstream_size+ bytestream_size+ wordstream_size + 20 != length + || bitstream_size > (1<<26) + || bytestream_size > (1<<26) + || wordstream_size > (1<<26) + ){ av_log(f->avctx, AV_LOG_ERROR, "lengths %d %d %d %d\n", bitstream_size, bytestream_size, wordstream_size, bitstream_size+ bytestream_size+ wordstream_size - length); + return -1; + } f->bitstream_buffer= av_fast_realloc(f->bitstream_buffer, &f->bitstream_buffer_size, bitstream_size + FF_INPUT_BUFFER_PADDING_SIZE); f->dsp.bswap_buf((uint32_t*)f->bitstream_buffer, (uint32_t*)(buf + 20), bitstream_size/4); @@ -550,13 +556,17 @@ static int decode_i_frame(FourXContext *f, uint8_t *buf, int length){ const int height= f->avctx->height; uint16_t *dst= (uint16_t*)f->current_picture.data[0]; const int stride= f->current_picture.linesize[0]>>1; - const int bitstream_size= get32(buf); + const unsigned int bitstream_size= get32(buf); const int token_count __attribute__((unused)) = get32(buf + bitstream_size + 8); - int prestream_size= 4*get32(buf + bitstream_size + 4); + unsigned int prestream_size= 4*get32(buf + bitstream_size + 4); uint8_t *prestream= buf + bitstream_size + 12; - if(prestream_size + bitstream_size + 12 != length) + if(prestream_size + bitstream_size + 12 != length + || bitstream_size > (1<<26) + || prestream_size > (1<<26)){ av_log(f->avctx, AV_LOG_ERROR, "size missmatch %d %d %d\n", prestream_size, bitstream_size, length); + return -1; + } prestream= read_huffman_tables(f, prestream); diff --git a/libavcodec/asv1.c b/libavcodec/asv1.c index c369c0ea2a..1a6b4a82d4 100644 --- a/libavcodec/asv1.c +++ b/libavcodec/asv1.c @@ -339,8 +339,13 @@ static inline int decode_mb(ASV1Context *a, DCTELEM block[6][64]){ return 0; } -static inline void encode_mb(ASV1Context *a, DCTELEM block[6][64]){ +static inline int encode_mb(ASV1Context *a, DCTELEM block[6][64]){ int i; + + if(a->pb.buf_end - a->pb.buf - (put_bits_count(&a->pb)>>3) < 30*16*16*3/2/8){ + av_log(a->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } if(a->avctx->codec_id == CODEC_ID_ASV1){ for(i=0; i<6; i++) @@ -349,6 +354,7 @@ static inline void encode_mb(ASV1Context *a, DCTELEM block[6][64]){ for(i=0; i<6; i++) asv2_encode_block(a, block[i]); } + return 0; } static inline void idct_put(ASV1Context *a, int mb_x, int mb_y){ diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 61b0d3f3b3..77f00cdb1c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -17,7 +17,7 @@ extern "C" { #define FFMPEG_VERSION_INT 0x000409 #define FFMPEG_VERSION "0.4.9-pre1" -#define LIBAVCODEC_BUILD 4736 +#define LIBAVCODEC_BUILD 4737 #define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT #define LIBAVCODEC_VERSION FFMPEG_VERSION @@ -235,6 +235,12 @@ enum SampleFormat { */ #define FF_INPUT_BUFFER_PADDING_SIZE 8 +/** + * minimum encoding buffer size. + * used to avoid some checks during header writing + */ +#define FF_MIN_BUFFER_SIZE 16384 + /* motion estimation type, EPZS by default */ enum Motion_Est_ID { ME_ZERO = 1, @@ -2112,6 +2118,7 @@ int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic); void avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic); int avcodec_default_reget_buffer(AVCodecContext *s, AVFrame *pic); void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height); +int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h); enum PixelFormat avcodec_default_get_format(struct AVCodecContext *s, const enum PixelFormat * fmt); int avcodec_thread_init(AVCodecContext *s, int thread_count); diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 1e190a5cbd..f548bffd8b 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -931,7 +931,9 @@ static int dvvideo_encode_frame(AVCodecContext *c, uint8_t *buf, int buf_size, s->sys = dv_codec_profile(c); if (!s->sys) return -1; - + if(buf_size < s->sys->frame_size) + return -1; + c->pix_fmt = s->sys->pix_fmt; s->picture = *((AVFrame *)data); diff --git a/libavcodec/ffv1.c b/libavcodec/ffv1.c index b9d2806b88..cc15d902b2 100644 --- a/libavcodec/ffv1.c +++ b/libavcodec/ffv1.c @@ -354,7 +354,7 @@ static inline int get_vlc_symbol(GetBitContext *gb, VlcState * const state, int return ret; } -static inline void encode_line(FFV1Context *s, int w, int_fast16_t *sample[2], int plane_index, int bits){ +static inline int encode_line(FFV1Context *s, int w, int_fast16_t *sample[2], int plane_index, int bits){ PlaneContext * const p= &s->plane[plane_index]; RangeCoder * const c= &s->c; int x; @@ -362,6 +362,18 @@ static inline void encode_line(FFV1Context *s, int w, int_fast16_t *sample[2], i int run_count=0; int run_mode=0; + if(s->ac){ + if(c->bytestream_end - c->bytestream < w*20){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + }else{ + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < w*4){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + } + for(x=0; xpb, 1, 1); } s->run_index= run_index; + + return 0; } static void encode_plane(FFV1Context *s, uint8_t *src, int w, int h, int stride, int plane_index){ @@ -896,7 +910,7 @@ static int read_header(FFV1Context *f){ context_count=1; for(i=0; i<5; i++){ context_count*= read_quant_table(c, f->quant_table[i], context_count); - if(context_count < 0){ + if(context_count < 0 || context_count > 32768){ av_log(f->avctx, AV_LOG_ERROR, "read_quant_table error\n"); return -1; } diff --git a/libavcodec/flicvideo.c b/libavcodec/flicvideo.c index 99825cebc2..92cb8bd0b8 100644 --- a/libavcodec/flicvideo.c +++ b/libavcodec/flicvideo.c @@ -176,7 +176,7 @@ static int flic_decode_frame(AVCodecContext *avctx, for (j = 0; j < color_changes; j++) { /* wrap around, for good measure */ - if (palette_ptr >= 256) + if ((unsigned)palette_ptr >= 256) palette_ptr = 0; r = buf[stream_ptr++] << color_shift; diff --git a/libavcodec/h263.c b/libavcodec/h263.c index afb96727e4..441721f883 100644 --- a/libavcodec/h263.c +++ b/libavcodec/h263.c @@ -6115,7 +6115,7 @@ int flv_h263_decode_picture_header(MpegEncContext *s) width = height = 0; break; } - if ((width == 0) || (height == 0)) + if(avcodec_check_dimensions(s->avctx, width, height)) return -1; s->width = width; s->height = height; diff --git a/libavcodec/h263dec.c b/libavcodec/h263dec.c index 458307a84d..da94aede5a 100644 --- a/libavcodec/h263dec.c +++ b/libavcodec/h263dec.c @@ -724,9 +724,8 @@ retry: if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0 && s->divx_packed){ int current_pos= get_bits_count(&s->gb)>>3; int startcode_found=0; - - if( buf_size - current_pos > 5 - && buf_size - current_pos < BITSTREAM_BUFFER_SIZE){ + + if(buf_size - current_pos > 5){ int i; for(i=current_pos; ibitstream_buffer= av_fast_realloc( + s->bitstream_buffer, + &s->allocated_bitstream_buffer_size, + buf_size - current_pos + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos); s->bitstream_buffer_size= buf_size - current_pos; } diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 5267b25f2f..22106a9090 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -5862,6 +5862,10 @@ static inline int decode_seq_parameter_set(H264Context *h){ sps->gaps_in_frame_num_allowed_flag= get_bits1(&s->gb); sps->mb_width= get_ue_golomb(&s->gb) + 1; sps->mb_height= get_ue_golomb(&s->gb) + 1; + if((unsigned)sps->mb_width >= INT_MAX/16 || (unsigned)sps->mb_height >= INT_MAX/16 || + avcodec_check_dimensions(NULL, 16*sps->mb_width, 16*sps->mb_height)) + return -1; + sps->frame_mbs_only_flag= get_bits1(&s->gb); if(!sps->frame_mbs_only_flag) sps->mb_aff= get_bits1(&s->gb); diff --git a/libavcodec/huffyuv.c b/libavcodec/huffyuv.c index e8a9ffa86d..5dec85c0cf 100644 --- a/libavcodec/huffyuv.c +++ b/libavcodec/huffyuv.c @@ -65,13 +65,14 @@ typedef struct HYuvContext{ int context; int picture_number; int last_slice_end; - uint8_t __align8 temp[3][2560]; + uint8_t *temp[3]; uint64_t stats[3][256]; uint8_t len[3][256]; uint32_t bits[3][256]; VLC vlc[3]; AVFrame picture; - uint8_t __align8 bitstream_buffer[1024*1024*3]; //FIXME dynamic alloc or some other solution + uint8_t *bitstream_buffer; + int bitstream_buffer_size; DSPContext dsp; }HYuvContext; @@ -347,24 +348,36 @@ static int read_old_huffman_tables(HYuvContext *s){ #endif } -static int decode_init(AVCodecContext *avctx) -{ +static int common_init(AVCodecContext *avctx){ HYuvContext *s = avctx->priv_data; - int width, height; + int i; s->avctx= avctx; s->flags= avctx->flags; dsputil_init(&s->dsp, avctx); + + s->width= avctx->width; + s->height= avctx->height; + assert(s->width>0 && s->height>0); + + for(i=0; i<3; i++){ + s->temp[i]= av_malloc(avctx->width + 16); + } + return 0; +} + +static int decode_init(AVCodecContext *avctx) +{ + HYuvContext *s = avctx->priv_data; + + common_init(avctx); memset(s->vlc, 0, 3*sizeof(VLC)); - width= s->width= avctx->width; - height= s->height= avctx->height; avctx->coded_frame= &s->picture; - s->interlaced= height > 288; + s->interlaced= s->height > 288; s->bgr32=1; - assert(width && height); //if(avctx->extradata) // printf("extradata:%X, extradata_size:%d\n", *(uint32_t*)avctx->extradata, avctx->extradata_size); if(avctx->extradata_size){ @@ -474,20 +487,12 @@ static int store_table(HYuvContext *s, uint8_t *len, uint8_t *buf){ static int encode_init(AVCodecContext *avctx) { HYuvContext *s = avctx->priv_data; - int i, j, width, height; + int i, j; - s->avctx= avctx; - s->flags= avctx->flags; - - dsputil_init(&s->dsp, avctx); - - width= s->width= avctx->width; - height= s->height= avctx->height; + common_init(avctx); - assert(width && height); - - avctx->extradata= av_mallocz(1024*30); - avctx->stats_out= av_mallocz(1024*30); + avctx->extradata= av_mallocz(1024*30); // 256*3+4 == 772 + avctx->stats_out= av_mallocz(1024*30); // 21*256*3(%llu ) + 3(\n) + 1(0) = 16132 s->version=2; avctx->coded_frame= &s->picture; @@ -524,7 +529,7 @@ static int encode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_ERROR, "Error: per-frame huffman tables are not supported by huffyuv; use vcodec=ffvhuff\n"); return -1; } - if(s->interlaced != ( height > 288 )) + if(s->interlaced != ( s->height > 288 )) av_log(avctx, AV_LOG_INFO, "using huffyuv 2.2.0 or newer interlacing flag\n"); }else if(avctx->strict_std_compliance>=0){ av_log(avctx, AV_LOG_ERROR, "This codec is under development; files encoded with it may not be decodeable with future versions!!! Set vstrict=-1 to use it anyway.\n"); @@ -580,7 +585,7 @@ static int encode_init(AVCodecContext *avctx) if(s->context){ for(i=0; i<3; i++){ - int pels = width*height / (i?40:10); + int pels = s->width*s->height / (i?40:10); for(j=0; j<256; j++){ int d= FFMIN(j, 256-j); s->stats[i][j]= pels/(d+1); @@ -623,9 +628,14 @@ static void decode_gray_bitstream(HYuvContext *s, int count){ } } -static void encode_422_bitstream(HYuvContext *s, int count){ +static int encode_422_bitstream(HYuvContext *s, int count){ int i; + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 2*4*count){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + count/=2; if(s->flags&CODEC_FLAG_PASS1){ for(i=0; ipb, s->len[2][ s->temp[2][ i ] ], s->bits[2][ s->temp[2][ i ] ]); } } + return 0; } -static void encode_gray_bitstream(HYuvContext *s, int count){ +static int encode_gray_bitstream(HYuvContext *s, int count){ int i; + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 4*count){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + count/=2; if(s->flags&CODEC_FLAG_PASS1){ for(i=0; ipb, s->len[0][ s->temp[0][2*i+1] ], s->bits[0][ s->temp[0][2*i+1] ]); } } + return 0; } static void decode_bgr_bitstream(HYuvContext *s, int count){ @@ -756,6 +773,8 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 /* no supplementary picture */ if (buf_size == 0) return 0; + + s->bitstream_buffer= av_fast_realloc(s->bitstream_buffer, &s->bitstream_buffer_size, buf_size + FF_INPUT_BUFFER_PADDING_SIZE); s->dsp.bswap_buf((uint32_t*)s->bitstream_buffer, (uint32_t*)buf, buf_size/4); @@ -981,11 +1000,23 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8 return (get_bits_count(&s->gb)+31)/32*4; } +static int common_end(HYuvContext *s){ + int i; + + for(i=0; i<3; i++){ + av_freep(&s->temp[i]); + } + return 0; +} + static int decode_end(AVCodecContext *avctx) { HYuvContext *s = avctx->priv_data; int i; + common_end(s); + av_freep(&s->bitstream_buffer); + for(i=0; i<3; i++){ free_vlc(&s->vlc[i]); } @@ -1161,7 +1192,9 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, static int encode_end(AVCodecContext *avctx) { -// HYuvContext *s = avctx->priv_data; + HYuvContext *s = avctx->priv_data; + + common_end(s); av_freep(&avctx->extradata); av_freep(&avctx->stats_out); diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c index 33c01a68f4..1ba723a957 100644 --- a/libavcodec/imgconvert.c +++ b/libavcodec/imgconvert.c @@ -268,6 +268,9 @@ int avpicture_fill(AVPicture *picture, uint8_t *ptr, int size, w2, h2, size2; PixFmtInfo *pinfo; + if(avcodec_check_dimensions(NULL, width, height)) + goto fail; + pinfo = &pix_fmt_info[pix_fmt]; size = width * height; switch(pix_fmt) { @@ -344,6 +347,7 @@ int avpicture_fill(AVPicture *picture, uint8_t *ptr, picture->linesize[1] = 4; return size2 + 256 * 4; default: +fail: picture->data[0] = NULL; picture->data[1] = NULL; picture->data[2] = NULL; @@ -360,7 +364,7 @@ int avpicture_layout(const AVPicture* src, int pix_fmt, int width, int height, const unsigned char* s; int size = avpicture_get_size(pix_fmt, width, height); - if (size > dest_size) + if (size > dest_size || size < 0) return -1; if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) { @@ -1920,6 +1924,8 @@ int avpicture_alloc(AVPicture *picture, void *ptr; size = avpicture_get_size(pix_fmt, width, height); + if(size<0) + goto fail; ptr = av_malloc(size); if (!ptr) goto fail; diff --git a/libavcodec/imgresample.c b/libavcodec/imgresample.c index b4c5f360ad..3b74a82794 100644 --- a/libavcodec/imgresample.c +++ b/libavcodec/imgresample.c @@ -561,6 +561,8 @@ ImgReSampleContext *img_resample_full_init(int owidth, int oheight, s = av_mallocz(sizeof(ImgReSampleContext)); if (!s) return NULL; + if((unsigned)owidth >= UINT_MAX / (LINE_BUF_HEIGHT + NB_TAPS)) + return NULL; s->line_buf = av_mallocz(owidth * (LINE_BUF_HEIGHT + NB_TAPS)); if (!s->line_buf) goto fail; diff --git a/libavcodec/indeo3.c b/libavcodec/indeo3.c index 7e4cf01206..24e2160e5a 100644 --- a/libavcodec/indeo3.c +++ b/libavcodec/indeo3.c @@ -196,6 +196,10 @@ static unsigned long iv_decode_frame(Indeo3DecodeContext *s, hdr_height = le2me_16(*(uint16_t *)buf_pos); buf_pos += 2; hdr_width = le2me_16(*(uint16_t *)buf_pos); + + if(avcodec_check_dimensions(NULL, hdr_width, hdr_height)) + return -1; + buf_pos += 2; chroma_height = ((hdr_height >> 2) + 3) & 0x7ffc; chroma_width = ((hdr_width >> 2) + 3) & 0x7ffc; diff --git a/libavcodec/mem.c b/libavcodec/mem.c index 9eaa09ed62..6d0fadc290 100644 --- a/libavcodec/mem.c +++ b/libavcodec/mem.c @@ -45,6 +45,10 @@ void *av_malloc(unsigned int size) { void *ptr; + + /* lets disallow possible ambiguous cases */ + if(size > INT_MAX) + return NULL; #ifdef MEMALIGN_HACK int diff; @@ -93,6 +97,10 @@ void *av_malloc(unsigned int size) */ void *av_realloc(void *ptr, unsigned int size) { + /* lets disallow possible ambiguous cases */ + if(size > INT_MAX) + return NULL; + #ifdef MEMALIGN_HACK //FIXME this isnt aligned correctly though it probably isnt needed int diff; diff --git a/libavcodec/mjpeg.c b/libavcodec/mjpeg.c index daa28d3540..b09492dc7e 100644 --- a/libavcodec/mjpeg.c +++ b/libavcodec/mjpeg.c @@ -659,11 +659,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in mjpeg_picture_header(s); s->header_bits= put_bits_count(&s->pb); - + if(avctx->pix_fmt == PIX_FMT_RGBA32){ int x, y, i; const int linesize= p->linesize[0]; - uint16_t buffer[2048][4]; + uint16_t (*buffer)[4]= s->rd_scratchpad; int left[3], top[3], topleft[3]; for(i=0; i<3; i++){ @@ -674,6 +674,11 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in const int modified_predictor= y ? predictor : 1; uint8_t *ptr = p->data[0] + (linesize * y); + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < width*3*4){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + for(i=0; i<3; i++){ top[i]= left[i]= topleft[i]= buffer[0][i]; } @@ -707,6 +712,10 @@ static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, in const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; for(mb_y = 0; mb_y < mb_height; mb_y++) { + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } for(mb_x = 0; mb_x < mb_width; mb_x++) { if(mb_x==0 || mb_y==0){ for(i=0;i<3;i++) { @@ -1060,7 +1069,10 @@ static int mjpeg_decode_sof(MJpegDecodeContext *s) } height = get_bits(&s->gb, 16); width = get_bits(&s->gb, 16); + dprintf("sof0: picture: %dx%d\n", width, height); + if(avcodec_check_dimensions(s->avctx, width, height)) + return -1; nb_components = get_bits(&s->gb, 8); if (nb_components <= 0 || @@ -1228,11 +1240,14 @@ static int decode_block(MJpegDecodeContext *s, DCTELEM *block, static int ljpeg_decode_rgb_scan(MJpegDecodeContext *s, int predictor, int point_transform){ int i, mb_x, mb_y; - uint16_t buffer[2048][4]; + uint16_t buffer[32768][4]; int left[3], top[3], topleft[3]; const int linesize= s->linesize[0]; const int mask= (1<bits)-1; + if((unsigned)s->mb_width > 32768) //dynamic alloc + return -1; + for(i=0; i<3; i++){ buffer[0][i]= 1 << (s->bits + point_transform - 1); } diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c index 55c8601b26..ffb7e0f854 100644 --- a/libavcodec/mpegvideo.c +++ b/libavcodec/mpegvideo.c @@ -619,6 +619,9 @@ int MPV_common_init(MpegEncContext *s) return -1; } + if((s->width || s->height) && avcodec_check_dimensions(s->avctx, s->width, s->height)) + return -1; + dsputil_init(&s->dsp, s->avctx); DCT_common_init(s); @@ -742,9 +745,6 @@ int MPV_common_init(MpegEncContext *s) CHECKED_ALLOCZ(s->coded_block_base, y_size); s->coded_block= s->coded_block_base + s->b8_stride + 1; - /* divx501 bitstream reorder buffer */ - CHECKED_ALLOCZ(s->bitstream_buffer, BITSTREAM_BUFFER_SIZE); - /* cbp, ac_pred, pred_dir */ CHECKED_ALLOCZ(s->cbp_table , mb_array_size * sizeof(uint8_t)) CHECKED_ALLOCZ(s->pred_dir_table, mb_array_size * sizeof(uint8_t)) @@ -849,6 +849,8 @@ void MPV_common_end(MpegEncContext *s) av_freep(&s->mbskip_table); av_freep(&s->prev_pict_types); av_freep(&s->bitstream_buffer); + s->allocated_bitstream_buffer_size=0; + av_freep(&s->avctx->stats_out); av_freep(&s->ac_stats); av_freep(&s->error_status_table); @@ -2314,6 +2316,11 @@ int MPV_encode_picture(AVCodecContext *avctx, stuffing_count= ff_vbv_update(s, s->frame_bits); if(stuffing_count){ + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < stuffing_count + 50){ + av_log(s->avctx, AV_LOG_ERROR, "stuffing too large\n"); + return -1; + } + switch(s->codec_id){ case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: @@ -4555,16 +4562,16 @@ static int encode_thread(AVCodecContext *c, void *arg){ int mb_x, mb_y, pdif = 0; int i, j; MpegEncContext best_s, backup_s; - uint8_t bit_buf[2][3000]; - uint8_t bit_buf2[2][3000]; - uint8_t bit_buf_tex[2][3000]; + uint8_t bit_buf[2][MAX_MB_BYTES]; + uint8_t bit_buf2[2][MAX_MB_BYTES]; + uint8_t bit_buf_tex[2][MAX_MB_BYTES]; PutBitContext pb[2], pb2[2], tex_pb[2]; //printf("%d->%d\n", s->resync_mb_y, s->end_mb_y); for(i=0; i<2; i++){ - init_put_bits(&pb [i], bit_buf [i], 3000); - init_put_bits(&pb2 [i], bit_buf2 [i], 3000); - init_put_bits(&tex_pb[i], bit_buf_tex[i], 3000); + init_put_bits(&pb [i], bit_buf [i], MAX_MB_BYTES); + init_put_bits(&pb2 [i], bit_buf2 [i], MAX_MB_BYTES); + init_put_bits(&tex_pb[i], bit_buf_tex[i], MAX_MB_BYTES); } s->last_bits= put_bits_count(&s->pb); @@ -4622,6 +4629,18 @@ static int encode_thread(AVCodecContext *c, void *arg){ int dmin= INT_MAX; int dir; + if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < MAX_MB_BYTES){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + if(s->data_partitioning){ + if( s->pb2 .buf_end - s->pb2 .buf - (put_bits_count(&s-> pb2)>>3) < MAX_MB_BYTES + || s->tex_pb.buf_end - s->tex_pb.buf - (put_bits_count(&s->tex_pb )>>3) < MAX_MB_BYTES){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + } + s->mb_x = mb_x; s->mb_y = mb_y; // moved into loop, can get changed by H.261 ff_update_block_index(s); diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h index 49682952ac..920d8c7061 100644 --- a/libavcodec/mpegvideo.h +++ b/libavcodec/mpegvideo.h @@ -68,6 +68,8 @@ enum OutputFormat { #define SI_TYPE FF_SI_TYPE ///< Switching Intra #define SP_TYPE FF_SP_TYPE ///< Switching Predicted +#define MAX_MB_BYTES (30*16*16*3/8 + 120) + typedef struct Predictor{ double coeff; double count; @@ -599,9 +601,9 @@ typedef struct MpegEncContext { int divx_version; int divx_build; int divx_packed; -#define BITSTREAM_BUFFER_SIZE 1024*256 uint8_t *bitstream_buffer; //Divx 5.01 puts several frames in a single one, this is used to reorder them int bitstream_buffer_size; + int allocated_bitstream_buffer_size; int xvid_build; diff --git a/libavcodec/png.c b/libavcodec/png.c index 11faa866ae..2945d0cc54 100644 --- a/libavcodec/png.c +++ b/libavcodec/png.c @@ -140,6 +140,8 @@ static int png_probe(AVProbeData *pd) #endif static void *png_zalloc(void *opaque, unsigned int items, unsigned int size) { + if(items >= UINT_MAX / size) + return NULL; return av_malloc(items * size); } @@ -522,6 +524,10 @@ static int decode_frame(AVCodecContext *avctx, goto fail; s->width = get32(&s->bytestream); s->height = get32(&s->bytestream); + if(avcodec_check_dimensions(avctx, s->width, s->height)){ + s->width= s->height= 0; + goto fail; + } s->bit_depth = *s->bytestream++; s->color_type = *s->bytestream++; s->compression_type = *s->bytestream++; @@ -727,7 +733,8 @@ static int png_write_row(PNGContext *s, const uint8_t *data, int size) if (ret != Z_OK) return -1; if (s->zstream.avail_out == 0) { - png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE); + if(s->bytestream_end - s->bytestream > IOBUF_SIZE + 100) + png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, IOBUF_SIZE); s->zstream.avail_out = IOBUF_SIZE; s->zstream.next_out = s->buf; } @@ -895,7 +902,7 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, ret = deflate(&s->zstream, Z_FINISH); if (ret == Z_OK || ret == Z_STREAM_END) { len = IOBUF_SIZE - s->zstream.avail_out; - if (len > 0) { + if (len > 0 && s->bytestream_end - s->bytestream > len + 100) { png_write_chunk(&s->bytestream, MKTAG('I', 'D', 'A', 'T'), s->buf, len); } s->zstream.avail_out = IOBUF_SIZE; diff --git a/libavcodec/pnm.c b/libavcodec/pnm.c index 1bfbf17ecc..51134ce370 100644 --- a/libavcodec/pnm.c +++ b/libavcodec/pnm.c @@ -109,8 +109,9 @@ static int pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){ } } /* check that all tags are present */ - if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0') + if (w <= 0 || h <= 0 || maxval <= 0 || depth <= 0 || tuple_type[0] == '\0' || avcodec_check_dimensions(avctx, w, h)) return -1; + avctx->width = w; avctx->height = h; if (depth == 1) { @@ -135,7 +136,7 @@ static int pnm_decode_header(AVCodecContext *avctx, PNMContext * const s){ return -1; pnm_get(s, buf1, sizeof(buf1)); avctx->height = atoi(buf1); - if (avctx->height <= 0) + if(avcodec_check_dimensions(avctx, avctx->width, avctx->height)) return -1; if (avctx->pix_fmt != PIX_FMT_MONOWHITE) { pnm_get(s, buf1, sizeof(buf1)); @@ -264,6 +265,11 @@ static int pnm_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int bu int i, h, h1, c, n, linesize; uint8_t *ptr, *ptr1, *ptr2; + if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){ + av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + *p = *pict; p->pict_type= FF_I_TYPE; p->key_frame= 1; @@ -338,6 +344,11 @@ static int pam_encode_frame(AVCodecContext *avctx, unsigned char *outbuf, int bu const char *tuple_type; uint8_t *ptr; + if(buf_size < avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height) + 200){ + av_log(avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } + *p = *pict; p->pict_type= FF_I_TYPE; p->key_frame= 1; diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c index 473645def4..a304f48f1a 100644 --- a/libavcodec/ratecontrol.c +++ b/libavcodec/ratecontrol.c @@ -74,6 +74,8 @@ int ff_rate_control_init(MpegEncContext *s) p= strchr(p+1, ';'); } i+= s->max_b_frames; + if(i<=0 || i>=INT_MAX / sizeof(RateControlEntry)) + return -1; rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry)); rcc->num_entries= i; diff --git a/libavcodec/snow.c b/libavcodec/snow.c index c9d47a8aa1..a84ec7e6c4 100644 --- a/libavcodec/snow.c +++ b/libavcodec/snow.c @@ -1292,7 +1292,7 @@ void ff_spatial_idwt(DWTELEM *buffer, int width, int height, int stride, int typ } } -static void encode_subband_c0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){ +static int encode_subband_c0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTELEM *parent, int stride, int orientation){ const int w= b->width; const int h= b->height; int x, y; @@ -1347,6 +1347,10 @@ static void encode_subband_c0run(SnowContext *s, SubBand *b, DWTELEM *src, DWTEL put_symbol2(&s->c, b->state[1], run, 3); for(y=0; yc.bytestream_end - &s->c.bytestream < w*40){ + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } for(x=0; xb_height; for(y=0; yc.bytestream_end - &s->c.bytestream < w*MB_SIZE*MB_SIZE*3){ //FIXME nicer limit + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return; + } for(x=0; xpb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < 3000){ //FIXME check size + av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); + return -1; + } s->m.mb_x= x; ff_init_block_index(&s->m); @@ -1280,6 +1285,7 @@ static void svq1_encode_plane(SVQ1Context *s, int plane, unsigned char *src_plan } s->m.first_slice_line=0; } + return 0; } static int svq1_encode_init(AVCodecContext *avctx) @@ -1341,10 +1347,11 @@ static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf, svq1_write_header(s, p->pict_type); for(i=0; i<3; i++){ - svq1_encode_plane(s, i, + if(svq1_encode_plane(s, i, s->picture.data[i], s->last_picture.data[i], s->current_picture.data[i], s->frame_width / (i?4:1), s->frame_height / (i?4:1), - s->picture.linesize[i], s->current_picture.linesize[i]); + s->picture.linesize[i], s->current_picture.linesize[i]) < 0) + return -1; } // align_put_bits(&s->pb); diff --git a/libavcodec/utils.c b/libavcodec/utils.c index aa042c795a..4111a63098 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -82,7 +82,7 @@ void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) if(min_size < *size) return ptr; - *size= 17*min_size/16 + 32; + *size= FFMAX(17*min_size/16 + 32, min_size); return av_realloc(ptr, *size); } @@ -101,6 +101,8 @@ void *av_mallocz_static(unsigned int size) if(ptr){ array_static =av_fast_realloc(array_static, &allocated_static, sizeof(void*)*(last_static+1)); + if(!array_static) + return NULL; array_static[last_static++] = ptr; } @@ -233,16 +235,27 @@ void avcodec_align_dimensions(AVCodecContext *s, int *width, int *height){ *height= ALIGN(*height, h_align); } +int avcodec_check_dimensions(void *av_log_ctx, unsigned int w, unsigned int h){ + if((int)w>0 && (int)h>0 && (w+128)*(uint64_t)(h+128) < INT_MAX/4) + return 0; + + av_log(av_log_ctx, AV_LOG_ERROR, "picture size invalid (%ux%u)\n", w, h); + return -1; +} + int avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){ int i; int w= s->width; int h= s->height; InternalBuffer *buf; int *picture_number; - + assert(pic->data[0]==NULL); assert(INTERNAL_BUFFER_SIZE > s->internal_buffer_count); + if(avcodec_check_dimensions(s,w,h)) + return -1; + if(s->internal_buffer==NULL){ s->internal_buffer= av_mallocz(INTERNAL_BUFFER_SIZE*sizeof(InternalBuffer)); } @@ -509,6 +522,11 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec) else if(avctx->width && avctx->height) avcodec_set_dimensions(avctx, avctx->width, avctx->height); + if((avctx->coded_width||avctx->coded_height) && avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height)){ + av_freep(&avctx->priv_data); + return -1; + } + ret = avctx->codec->init(avctx); if (ret < 0) { av_freep(&avctx->priv_data); @@ -520,6 +538,10 @@ int avcodec_open(AVCodecContext *avctx, AVCodec *codec) int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, const short *samples) { + if(buf_size < FF_MIN_BUFFER_SIZE && 0){ + av_log(avctx, AV_LOG_ERROR, "buffer smaller then minimum size\n"); + return -1; + } if((avctx->codec->capabilities & CODEC_CAP_DELAY) || samples){ int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)samples); avctx->frame_number++; @@ -531,6 +553,12 @@ int avcodec_encode_audio(AVCodecContext *avctx, uint8_t *buf, int buf_size, int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size, const AVFrame *pict) { + if(buf_size < FF_MIN_BUFFER_SIZE){ + av_log(avctx, AV_LOG_ERROR, "buffer smaller then minimum size\n"); + return -1; + } + if(avcodec_check_dimensions(avctx,avctx->width,avctx->height)) + return -1; if((avctx->codec->capabilities & CODEC_CAP_DELAY) || pict){ int ret = avctx->codec->encode(avctx, buf, buf_size, (void *)pict); avctx->frame_number++; @@ -557,6 +585,8 @@ int avcodec_decode_video(AVCodecContext *avctx, AVFrame *picture, int ret; *got_picture_ptr= 0; + if((avctx->coded_width||avctx->coded_height) && avcodec_check_dimensions(avctx,avctx->coded_width,avctx->coded_height)) + return -1; ret = avctx->codec->decode(avctx, picture, got_picture_ptr, buf, buf_size); diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c index 4c7976cde9..8b90438d20 100644 --- a/libavcodec/vp3.c +++ b/libavcodec/vp3.c @@ -2093,6 +2093,9 @@ static void render_fragments(Vp3DecodeContext *s, upper_motion_limit = 7 * s->current_frame.linesize[2]; lower_motion_limit = height * s->current_frame.linesize[2] + width - 8; } + + if((unsigned)stride > 2048) + return; //various tables are fixed size /* for each fragment row... */ for (y = 0; y < height; y += 8) { @@ -2681,6 +2684,11 @@ static int theora_decode_header(AVCodecContext *avctx, GetBitContext gb) s->width = get_bits(&gb, 16) << 4; s->height = get_bits(&gb, 16) << 4; + if(avcodec_check_dimensions(avctx, s->width, s->height)){ + s->width= s->height= 0; + return -1; + } + skip_bits(&gb, 24); /* frame width */ skip_bits(&gb, 24); /* frame height */ diff --git a/libavcodec/vqavideo.c b/libavcodec/vqavideo.c index ea86fb1086..fb0871e182 100644 --- a/libavcodec/vqavideo.c +++ b/libavcodec/vqavideo.c @@ -151,6 +151,10 @@ static int vqa_decode_init(AVCodecContext *avctx) s->vqa_version = vqa_header[0]; s->width = LE_16(&vqa_header[6]); s->height = LE_16(&vqa_header[8]); + if(avcodec_check_dimensions(avctx, s->width, s->height)){ + s->width= s->height= 0; + return -1; + } s->vector_width = vqa_header[10]; s->vector_height = vqa_header[11]; s->partial_count = s->partial_countdown = vqa_header[13]; diff --git a/libavcodec/xan.c b/libavcodec/xan.c index f98a06bca9..377a71ef2c 100644 --- a/libavcodec/xan.c +++ b/libavcodec/xan.c @@ -132,6 +132,9 @@ static int xan_decode_init(AVCodecContext *avctx) v_b_table[i] = V_B * i; } + if(avcodec_check_dimensions(avctx, avctx->width, avctx->height)) + return -1; + s->buffer1 = av_malloc(avctx->width * avctx->height); s->buffer2 = av_malloc(avctx->width * avctx->height); if (!s->buffer1 || !s->buffer2) -- cgit v1.2.3