Commit 0ecca7a4 authored by Michael Niedermayer's avatar Michael Niedermayer

various security fixes and precautionary checks

Originally committed as revision 3822 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent f14d4e7e
......@@ -35,10 +35,10 @@ void show_help_options(const OptionDef *options, const char *msg, int mask, int
printf("%s", msg);
first = 0;
}
strcpy(buf, po->name);
pstrcpy(buf, sizeof(buf), po->name);
if (po->flags & HAS_ARG) {
strcat(buf, " ");
strcat(buf, po->argname);
pstrcat(buf, sizeof(buf), " ");
pstrcat(buf, sizeof(buf), po->argname);
}
printf("-%-17s %s\n", buf, po->help);
}
......
......@@ -1020,21 +1020,21 @@ static void print_report(AVFormatContext **output_files,
os = output_files[ost->file_index];
enc = &ost->st->codec;
if (vid && enc->codec_type == CODEC_TYPE_VIDEO) {
sprintf(buf + strlen(buf), "q=%2.1f ",
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "q=%2.1f ",
enc->coded_frame->quality/(float)FF_QP2LAMBDA);
}
if (!vid && enc->codec_type == CODEC_TYPE_VIDEO) {
frame_number = ost->frame_number;
sprintf(buf + strlen(buf), "frame=%5d q=%2.1f ",
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "frame=%5d q=%2.1f ",
frame_number, enc->coded_frame ? enc->coded_frame->quality/(float)FF_QP2LAMBDA : 0);
if(is_last_report)
sprintf(buf + strlen(buf), "L");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "L");
if (enc->flags&CODEC_FLAG_PSNR){
int j;
double error, error_sum=0;
double scale, scale_sum=0;
char type[3]= {'Y','U','V'};
sprintf(buf + strlen(buf), "PSNR=");
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "PSNR=");
for(j=0; j<3; j++){
if(is_last_report){
error= enc->error[j];
......@@ -1046,9 +1046,9 @@ static void print_report(AVFormatContext **output_files,
if(j) scale/=4;
error_sum += error;
scale_sum += scale;
sprintf(buf + strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%c:%2.2f ", type[j], psnr(error/scale));
}
sprintf(buf + strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "*:%2.2f ", psnr(error_sum/scale_sum));
}
vid = 1;
}
......@@ -1063,12 +1063,12 @@ static void print_report(AVFormatContext **output_files,
if (verbose || is_last_report) {
bitrate = (double)(total_size * 8) / ti1 / 1000.0;
sprintf(buf + strlen(buf),
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"size=%8.0fkB time=%0.1f bitrate=%6.1fkbits/s",
(double)total_size / 1024, ti1, bitrate);
if (verbose > 1)
sprintf(buf + strlen(buf), " dup=%d drop=%d",
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " dup=%d drop=%d",
nb_frames_dup, nb_frames_drop);
if (verbose >= 0)
......@@ -3331,7 +3331,7 @@ static void opt_output_file(const char *filename)
output_files[nb_output_files++] = oc;
strcpy(oc->filename, filename);
pstrcpy(oc->filename, sizeof(oc->filename), filename);
/* check filename in case of an image number is expected */
if (oc->oformat->flags & AVFMT_NEEDNUMBER) {
......
......@@ -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);
......
......@@ -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){
......
......@@ -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);
......
......@@ -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);
......
......@@ -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; x<w; x++){
int diff, context;
......@@ -416,6 +428,8 @@ static inline void encode_line(FFV1Context *s, int w, int_fast16_t *sample[2], i
put_bits(&s->pb, 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;
}
......
......@@ -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;
......
......@@ -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;
......
......@@ -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; i<buf_size-3; i++){
if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){
......@@ -741,6 +740,10 @@ retry:
}
if(startcode_found){
s->bitstream_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;
}
......
......@@ -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);
......
......@@ -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; i<count; i++){
......@@ -653,11 +663,17 @@ static void encode_422_bitstream(HYuvContext *s, int count){
put_bits(&s->pb, 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; i<count; i++){
......@@ -677,6 +693,7 @@ static void encode_gray_bitstream(HYuvContext *s, int count){
put_bits(&s->pb, 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);
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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);