Backports of the following commits: d19ea1ce173e95c31b0e8acbe471ea26c292be2b (CVE-2022-38850) [PATCH] vd.c: sanity-check aspect adjustment 58db9292a414ebf13a2cacdb3ffa967fb9036935 (CVE-2022-38851) PATCH] asfheader.c: Fix CHECKDEC macro. 2f6e69e59e2614acdde5505b049c48f80a3d0eb7 (CVE-2022-38855) [PATCH] demux_mov.c: Add bounds checks to debug prints. 92e0d0b1a04dfdd4ac741e0d07005e3ece2c92ca (CVE-2022-38858) [PATCH] demux_mov.c: robustness fixes. 62fe0c63cf4fba91efd29bbc85309280e1a99a47 (CVE-2022-38860) [PATCH] demux_avi.c: check that sh->wf exists before using it. 2622e7fbe3605a2f3b4f74900197fefeedc0d2e1 (CVE-2022-38861) [PATCH] mp_image.c: fix allocation size for formats with odd width. b5e745b4bfab2835103a060094fae3c6cc1ba17d (CVE-2022-38863) [PATCH] mpeg_hdr.c: Allocate 0xff initialized padding. 36546389ef9fb6b0e0540c5c3f212534c34b0e94 (CVE-2022-38864) [PATCH] mpeg_hdr.c: Fix unescape code. 33d9295663c37a37216633d7e3f07e7155da6144 (CVE-2022-38865) [PATCH] demux_avi.c: Fixup invalid audio block size. 373517da3bb5781726565eb3114a2697b13f00f2 (CVE-2022-38866) [PATCH] aviheader.c: Fix allocation size for vprp --- mplayer-1.4+ds1.orig/libmpcodecs/mp_image.c +++ mplayer-1.4+ds1/libmpcodecs/mp_image.c @@ -51,8 +51,12 @@ void mp_image_alloc_planes(mp_image_t *m } mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8+ mpi->chroma_width*mpi->chroma_height); - } else - mpi->planes[0]=av_malloc(mpi->bpp*mpi->width*(mpi->height+2)/8); + } else { + // for odd width round up to be on the safe side, + // required in particular for planar formats + int alloc_w = mpi->width + (mpi->width & 1); + mpi->planes[0]=av_malloc(mpi->bpp*alloc_w*(mpi->height+2)/8); + } if (mpi->flags&MP_IMGFLAG_PLANAR) { int bpp = IMGFMT_IS_YUVP16(mpi->imgfmt)? 2 : 1; // YV12/I420/YVU9/IF09. feel free to add other planar formats here... --- mplayer-1.4+ds1.orig/libmpcodecs/vd.c +++ mplayer-1.4+ds1/libmpcodecs/vd.c @@ -332,7 +332,7 @@ int mpcodecs_config_vo(sh_video_t *sh, i screen_size_y = screen_size_xy * sh->disp_h / sh->disp_w; } } - if (sh->aspect >= 0.01) { + if (sh->aspect >= 0.01 && sh->aspect <= 100) { int w; mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_MovieAspectIsSet, sh->aspect); @@ -350,6 +350,8 @@ int mpcodecs_config_vo(sh_video_t *sh, i } else { mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_MovieAspectUndefined); } + if (screen_size_x < 2) screen_size_x = 2; + if (screen_size_y < 2) screen_size_y = 2; } vocfg_flags = (fullscreen ? VOFLAG_FULLSCREEN : 0) --- mplayer-1.4+ds1.orig/libmpdemux/asfheader.c +++ mplayer-1.4+ds1/libmpdemux/asfheader.c @@ -234,7 +234,7 @@ static int get_ext_stream_properties(cha return 1; } -#define CHECKDEC(l, n) if (((l) -= (n)) < 0) return 0 +#define CHECKDEC(l, n) if ((l) < (n)) return 0; (l) -= (n) static char* read_meta_record(ASF_meta_record_t* dest, char* buf, int* buf_len) { --- mplayer-1.4+ds1.orig/libmpdemux/aviheader.c +++ mplayer-1.4+ds1/libmpdemux/aviheader.c @@ -327,7 +327,7 @@ while(1){ } } else if(last_fccType==streamtypeAUDIO){ - unsigned wf_size = chunksize<sizeof(*sh_audio->wf)?sizeof(*sh_audio->wf):chunksize; + unsigned wf_size = FFMAX(chunksize, sizeof(*sh_audio->wf)); sh_audio->wf=calloc(wf_size,1); // sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize); mp_msg(MSGT_HEADER, MSGL_V, "Found 'wf', %u bytes of %zu\n", @@ -355,7 +355,7 @@ while(1){ break; } case mmioFOURCC('v', 'p', 'r', 'p'): { - VideoPropHeader *vprp = malloc(chunksize); + VideoPropHeader *vprp = calloc(1, FFMAX(chunksize, sizeof(*vprp))); unsigned int i; stream_read(demuxer->stream, (void*)vprp, chunksize); le2me_VideoPropHeader(vprp); @@ -368,7 +368,7 @@ while(1){ for (i=0; i<vprp->nbFieldPerFrame; i++) { le2me_VIDEO_FIELD_DESC(&vprp->FieldInfo[i]); } - if (sh_video) { + if (sh_video && VALID_AVI_ASPECT(vprp->dwFrameAspectRatio)) { sh_video->original_aspect = GET_AVI_ASPECT(vprp->dwFrameAspectRatio); } if( mp_msg_test(MSGT_HEADER,MSGL_V) ) print_vprp(vprp,MSGL_V); --- mplayer-1.4+ds1.orig/libmpdemux/aviheader.h +++ mplayer-1.4+ds1/libmpdemux/aviheader.h @@ -219,6 +219,7 @@ typedef enum { } VIDEO_STANDARD; #define MAKE_AVI_ASPECT(a, b) (((a)<<16)|(b)) +#define VALID_AVI_ASPECT(a) (((a)>>16) && ((a) & 0xffff)) #define GET_AVI_ASPECT(a) ((float)((a)>>16)/(float)((a)&0xffff)) /* --- mplayer-1.4+ds1.orig/libmpdemux/demux_avi.c +++ mplayer-1.4+ds1/libmpdemux/demux_avi.c @@ -63,6 +63,7 @@ static void update_audio_block_size(demu } } } + if (priv->audio_block_size < 1) priv->audio_block_size = 1; } // Select ds from ID @@ -139,8 +140,9 @@ static int demux_avi_read_packet(demuxer if(priv->pts_has_video){ // we have video pts now float delay=0; - if(((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec) - delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec; + sh_audio_t *sh = (sh_audio_t *)ds->sh; + if(sh->wf && sh->wf->nAvgBytesPerSec) + delay=(float)priv->pts_corr_bytes/sh->wf->nAvgBytesPerSec; mp_msg(MSGT_DEMUX,MSGL_V,"XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay); //priv->pts_correction=-priv->avi_audio_pts+delay; priv->pts_correction=delay-priv->avi_audio_pts; --- mplayer-1.4+ds1.orig/libmpdemux/demux_mov.c +++ mplayer-1.4+ds1/libmpdemux/demux_mov.c @@ -298,6 +298,10 @@ static void mov_build_index(mov_track_t* for(;sample<trak->samples_size;sample++){ if(pts<=trak->samples[sample].pts) break; } + if (sample >= trak->samples_size){ + // skip! + el->frames=0; continue; + } el->start_sample=sample; el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts; pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale; @@ -1088,6 +1092,7 @@ static int gen_sh_video(sh_video_t* sh, // Parse some parts of avcC, just for fun :) // real parsing is done by avc1 decoder mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); + if (atom_len >= 14) { if (*(trak->stdata+pos+8) != 1) mp_msg(MSGT_DEMUX, MSGL_ERR, "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); @@ -1097,15 +1102,19 @@ static int gen_sh_video(sh_video_t* sh, mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); poffs = pos + 14; for (i = 0; i < cnt; i++) { + if (poffs - pos + 4 > atom_len) break; mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC sps %d have length %d\n", i, AV_RB16(trak->stdata+poffs)); poffs += AV_RB16(trak->stdata+poffs) + 2; } - mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); + if (poffs - pos < atom_len) + mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); poffs++; for (i = 0; i < cnt; i++) { + if (poffs - pos + 4 > atom_len) break; mp_msg(MSGT_DEMUX, MSGL_V, "MOV: avcC pps %d have length %d\n", i, AV_RB16(trak->stdata+poffs)); poffs += AV_RB16(trak->stdata+poffs) + 2; } + } // Copy avcC for the AVC decoder // This data will be put in extradata below, where BITMAPINFOHEADER is created trak->stream_header_len = atom_len-8; @@ -1310,6 +1319,10 @@ static void lschunks(demuxer_t* demuxer, int version = stream_read_char(demuxer->stream); stream_skip(demuxer->stream, (version == 1) ? 19 : 11); priv->timescale=stream_read_dword(demuxer->stream); + if (priv->timescale <= 0) { + priv->timescale = 600; + mp_msg(MSGT_DEMUX, MSGL_INFO,"MOV: invalid timescale, defaulting to %i\n", priv->timescale); + } if (version == 1) priv->duration=stream_read_qword(demuxer->stream); else --- mplayer-1.4+ds1.orig/libmpdemux/mpeg_hdr.c +++ mplayer-1.4+ds1/libmpdemux/mpeg_hdr.c @@ -374,9 +374,9 @@ static int mp_unescape03(uint8_t *dest, return 0; j = i = skip = 0; - while(i <= len-3) + while(i < len) { - if(buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3) + if(i <= len-3 && buf[i] == 0 && buf[i+1] == 0 && buf[i+2] == 3) { dest[j] = dest[j+1] = 0; j += 2; @@ -390,8 +390,6 @@ static int mp_unescape03(uint8_t *dest, i++; } } - dest[j] = buf[len-2]; - dest[j+1] = buf[len-1]; len -= skip; return len; @@ -401,7 +399,15 @@ int h264_parse_sps(mp_mpeg_header_t * pi { unsigned int n = 0, v, i, k, mbh; int frame_mbs_only; - uint8_t *buf = malloc(len); + uint8_t *buf; + // Sanity check, should not happen in MPlayer due to limited video buffer + if (len > 100*1024*1024) len = 100*1024*1024; + // Allocate more to allow for overread. + // Initialize to 0xff to minimize golomb length + // 4kB is more than necessary, but calculating the exact + // value or adding more range checks is more pain than worth it. + buf = malloc(len + 4096); + memset(buf, 0xff, len + 4096); len = mp_unescape03(buf, inbuf, len);