diff --git a/ffmpeg.spec b/ffmpeg.spec index d4213b207c6143066e959f903949e7c5c4ed6f80..d81786023ee5af0245b546181c8aa0f2068916b7 100644 --- a/ffmpeg.spec +++ b/ffmpeg.spec @@ -60,7 +60,7 @@ Summary: Digital VCR and streaming server Name: ffmpeg%{?flavor} Version: 4.2.4 -Release: 22 +Release: 23 License: %{ffmpeg_license} URL: http://ffmpeg.org/ %if 0%{?date} @@ -94,6 +94,7 @@ Patch22: backport-CVE-2024-36616.patch Patch23: backport-CVE-2024-36618.patch Patch24: backport-CVE-2024-36617.patch Patch25: backport-CVE-2024-36613.patch +Patch26: fix-CVE-2020.patch Requires: %{name}-libs%{?_isa} = %{version}-%{release} %{?_with_cuda:BuildRequires: cuda-minimal-build-%{_cuda_version_rpm} cuda-drivers-devel} @@ -427,6 +428,9 @@ install -pm755 tools/qt-faststart %{buildroot}%{_bindir} %changelog +* Fri Jul 4 2025 happyworker <208suo@208suo.com> - 4.2.4-23 +- Fix CVE-2020-22026/CVE-2020-22019/CVE-2020-22021/CVE-2020-22038/CVE-2020-22039/CVE-2020-22044/CVE-2020-22043 + * Sun Jan 5 2025 changtao - 4.2.4-22 - Type: CVE - CVE: CVE-2024-36613 diff --git a/fix-CVE-2020.patch b/fix-CVE-2020.patch new file mode 100644 index 0000000000000000000000000000000000000000..16b0067ad6337f1e1c1914be722d363a9201eb09 --- /dev/null +++ b/fix-CVE-2020.patch @@ -0,0 +1,375 @@ +From 478898b2bce89fca8370c51a567eb32e5e634513 Mon Sep 17 00:00:00 2001 +From: Michael Niedermayer +Date: Fri, 4 Jul 2025 14:57:21 +0800 +Subject: [PATCH] avfilter/vf_yadif: Fix handing of tiny images + +--- + libavcodec/v4l2_m2m.c | 18 +++++++++++------- + libavcodec/v4l2_m2m_dec.c | 2 -- + libavfilter/af_tremolo.c | 8 +++++--- + libavfilter/vf_vmafmotion.c | 4 ++++ + libavfilter/vf_yadif.c | 35 +++++++++++++++++++++-------------- + libavformat/avienc.c | 22 +++++++++++++++++----- + libavformat/mpegenc.c | 31 +++++++++++++++++++------------ + libavformat/nutenc.c | 2 +- + 8 files changed, 78 insertions(+), 44 deletions(-) + +diff --git a/libavcodec/v4l2_m2m.c b/libavcodec/v4l2_m2m.c +index 427e165..cfb4f14 100644 +--- a/libavcodec/v4l2_m2m.c ++++ b/libavcodec/v4l2_m2m.c +@@ -312,7 +312,7 @@ static void v4l2_m2m_destroy_context(void *opaque, uint8_t *context) + sem_destroy(&s->refsync); + + close(s->fd); +- ++ ; + av_free(s); + } + +@@ -322,14 +322,18 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx) + V4L2m2mContext* s = priv->context; + int ret; + +- ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); +- if (ret) +- av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); ++ if (!s) ++ return 0; + +- ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); +- if (ret) +- av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ if (s->fd >= 0) { ++ ret = ff_v4l2_context_set_status(&s->output, VIDIOC_STREAMOFF); ++ if (ret) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->output.name); + ++ ret = ff_v4l2_context_set_status(&s->capture, VIDIOC_STREAMOFF); ++ if (ret) ++ av_log(avctx, AV_LOG_ERROR, "VIDIOC_STREAMOFF %s\n", s->capture.name); ++ } + ff_v4l2_context_release(&s->output); + + s->self_ref = NULL; +diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c +index d0601f0..587d0d6 100644 +--- a/libavcodec/v4l2_m2m_dec.c ++++ b/libavcodec/v4l2_m2m_dec.c +@@ -190,8 +190,6 @@ static av_cold int v4l2_decode_init(AVCodecContext *avctx) + if (ret) { + V4L2m2mPriv *priv = avctx->priv_data; + av_log(avctx, AV_LOG_ERROR, "can't configure decoder\n"); +- s->self_ref = NULL; +- av_buffer_unref(&priv->context_ref); + + return ret; + } +diff --git a/libavfilter/af_tremolo.c b/libavfilter/af_tremolo.c +index 8cbc798..f55e8e2 100644 +--- a/libavfilter/af_tremolo.c ++++ b/libavfilter/af_tremolo.c +@@ -28,6 +28,7 @@ typedef struct TremoloContext { + double freq; + double depth; + double *table; ++ int table_size; + int index; + } TremoloContext; + +@@ -72,7 +73,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) + dst += channels; + src += channels; + s->index++; +- if (s->index >= inlink->sample_rate / s->freq) ++ if (s->index >= s->table_size) + s->index = 0; + } + +@@ -125,11 +126,12 @@ static int config_input(AVFilterLink *inlink) + const double offset = 1. - s->depth / 2.; + int i; + +- s->table = av_malloc_array(inlink->sample_rate / s->freq, sizeof(*s->table)); ++ s->table_size = inlink->sample_rate / s->freq; ++ s->table = av_malloc_array(s->table_size, sizeof(*s->table)); + if (!s->table) + return AVERROR(ENOMEM); + +- for (i = 0; i < inlink->sample_rate / s->freq; i++) { ++ for (i = 0; i < s->table_size; i++) { + double env = s->freq * i / inlink->sample_rate; + env = sin(2 * M_PI * fmod(env + 0.25, 1.0)); + s->table[i] = env * (1 - fabs(offset)) + offset; +diff --git a/libavfilter/vf_vmafmotion.c b/libavfilter/vf_vmafmotion.c +index 5c2a974..0bbb998 100644 +--- a/libavfilter/vf_vmafmotion.c ++++ b/libavfilter/vf_vmafmotion.c +@@ -238,6 +238,10 @@ int ff_vmafmotion_init(VMAFMotionData *s, + int i; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + ++ if (w < 3 || h < 3) ++ return AVERROR(EINVAL); ++ ++ + s->width = w; + s->height = h; + s->stride = FFALIGN(w * sizeof(uint16_t), 32); +diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c +index 3107924..3c7a46b 100644 +--- a/libavfilter/vf_yadif.c ++++ b/libavfilter/vf_yadif.c +@@ -123,20 +123,23 @@ static void filter_edges(void *dst1, void *prev1, void *cur1, void *next1, + uint8_t *next2 = parity ? cur : next; + + const int edge = MAX_ALIGN - 1; ++ int offset = FFMAX(w - edge, 3); + + /* Only edge pixels need to be processed here. A constant value of false + * for is_not_edge should let the compiler ignore the whole branch. */ +- FILTER(0, 3, 0) ++ FILTER(0, FFMIN(3, w), 0) ++ ++ dst = (uint8_t*)dst1 + offset; ++ prev = (uint8_t*)prev1 + offset; ++ cur = (uint8_t*)cur1 + offset; ++ next = (uint8_t*)next1 + offset; + +- dst = (uint8_t*)dst1 + w - edge; +- prev = (uint8_t*)prev1 + w - edge; +- cur = (uint8_t*)cur1 + w - edge; +- next = (uint8_t*)next1 + w - edge; + prev2 = (uint8_t*)(parity ? prev : cur); + next2 = (uint8_t*)(parity ? cur : next); + +- FILTER(w - edge, w - 3, 1) +- FILTER(w - 3, w, 0) ++ FILTER(offset, w - 3, 1) ++ offset = FFMAX(offset, w - 3); ++ FILTER(offset, w, 0) + } + + +@@ -170,21 +173,25 @@ static void filter_edges_16bit(void *dst1, void *prev1, void *cur1, void *next1, + uint16_t *next2 = parity ? cur : next; + + const int edge = MAX_ALIGN / 2 - 1; ++ int offset = FFMAX(w - edge, 3); + + mrefs /= 2; + prefs /= 2; + +- FILTER(0, 3, 0) ++ FILTER(0, FFMIN(3, w), 0) ++ ++ dst = (uint16_t*)dst1 + offset; ++ prev = (uint16_t*)prev1 + offset; ++ cur = (uint16_t*)cur1 + offset; ++ next = (uint16_t*)next1 + offset; + +- dst = (uint16_t*)dst1 + w - edge; +- prev = (uint16_t*)prev1 + w - edge; +- cur = (uint16_t*)cur1 + w - edge; +- next = (uint16_t*)next1 + w - edge; + prev2 = (uint16_t*)(parity ? prev : cur); + next2 = (uint16_t*)(parity ? cur : next); + +- FILTER(w - edge, w - 3, 1) +- FILTER(w - 3, w, 0) ++ FILTER(offset, w - 3, 1) ++ offset = FFMAX(offset, w - 3); ++ FILTER(offset, w, 0) ++ + } + + static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +diff --git a/libavformat/avienc.c b/libavformat/avienc.c +index 1b8904f..4170bf5 100644 +--- a/libavformat/avienc.c ++++ b/libavformat/avienc.c +@@ -917,7 +917,7 @@ static int avi_write_trailer(AVFormatContext *s) + AVIContext *avi = s->priv_data; + AVIOContext *pb = s->pb; + int res = 0; +- int i, j, n, nb_frames; ++ int i, n, nb_frames; + int64_t file_size; + + for (i = 0; i < s->nb_streams; i++) { +@@ -970,10 +970,6 @@ static int avi_write_trailer(AVFormatContext *s) + + for (i = 0; i < s->nb_streams; i++) { + AVIStream *avist = s->streams[i]->priv_data; +- for (j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) +- av_freep(&avist->indexes.cluster[j]); +- av_freep(&avist->indexes.cluster); +- avist->indexes.ents_allocated = avist->indexes.entry = 0; + if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + avio_seek(pb, avist->frames_hdr_strm + 4, SEEK_SET); + avio_wl32(pb, avist->max_size); +@@ -983,6 +979,21 @@ static int avi_write_trailer(AVFormatContext *s) + return res; + } + ++static void avi_deinit(AVFormatContext *s) ++{ ++ for (int i = 0; i < s->nb_streams; i++) { ++ AVIStream *avist = s->streams[i]->priv_data; ++ if (!avist) ++ continue; ++ for (int j = 0; j < avist->indexes.ents_allocated / AVI_INDEX_CLUSTER_SIZE; j++) ++ av_freep(&avist->indexes.cluster[j]); ++ av_freep(&avist->indexes.cluster); ++ avist->indexes.ents_allocated = avist->indexes.entry = 0; ++ } ++} ++ ++ ++ + #define OFFSET(x) offsetof(AVIContext, x) + #define ENC AV_OPT_FLAG_ENCODING_PARAM + static const AVOption options[] = { +@@ -1007,6 +1018,7 @@ AVOutputFormat ff_avi_muxer = { + .audio_codec = CONFIG_LIBMP3LAME ? AV_CODEC_ID_MP3 : AV_CODEC_ID_AC3, + .video_codec = AV_CODEC_ID_MPEG4, + .init = avi_init, ++ .deinit = avi_deinit, + .write_header = avi_write_header, + .write_packet = avi_write_packet, + .write_trailer = avi_write_trailer, +diff --git a/libavformat/mpegenc.c b/libavformat/mpegenc.c +index 1b0b532..789431a 100644 +--- a/libavformat/mpegenc.c ++++ b/libavformat/mpegenc.c +@@ -315,7 +315,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + if (ctx->packet_size < 20 || ctx->packet_size > (1 << 23) + 10) { + av_log(ctx, AV_LOG_ERROR, "Invalid packet size %d\n", + ctx->packet_size); +- goto fail; ++ return AVERROR(EINVAL); + } + s->packet_size = ctx->packet_size; + } else +@@ -343,7 +343,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + st = ctx->streams[i]; + stream = av_mallocz(sizeof(StreamInfo)); + if (!stream) +- goto fail; ++ return AVERROR(EINVAL); + st->priv_data = stream; + + avpriv_set_pts_info(st, 64, 1, 90000); +@@ -377,11 +377,11 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + for (sr = 0; sr < 4; sr++) + av_log(ctx, AV_LOG_INFO, " %d", lpcm_freq_tab[sr]); + av_log(ctx, AV_LOG_INFO, "\n"); +- goto fail; ++ return AVERROR(EINVAL); + } + if (st->codecpar->channels > 8) { + av_log(ctx, AV_LOG_ERROR, "At most 8 channels allowed for LPCM streams.\n"); +- goto fail; ++ return AVERROR(EINVAL); + } + stream->lpcm_header[0] = 0x0c; + stream->lpcm_header[1] = (st->codecpar->channels - 1) | (j << 4); +@@ -416,7 +416,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + st->codecpar->codec_id != AV_CODEC_ID_MP2 && + st->codecpar->codec_id != AV_CODEC_ID_MP3) { + av_log(ctx, AV_LOG_ERROR, "Unsupported audio codec. Must be one of mp1, mp2, mp3, 16-bit pcm_dvd, pcm_s16be, ac3 or dts.\n"); +- goto fail; ++ return AVERROR(EINVAL); + } else { + stream->id = mpa_id++; + } +@@ -460,7 +460,7 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + } + stream->fifo = av_fifo_alloc(16); + if (!stream->fifo) +- goto fail; ++ return AVERROR(EINVAL); + } + bitrate = 0; + audio_bitrate = 0; +@@ -560,11 +560,6 @@ static av_cold int mpeg_mux_init(AVFormatContext *ctx) + s->system_header_size = get_system_header_size(ctx); + s->last_scr = AV_NOPTS_VALUE; + return 0; +- +-fail: +- for (i = 0; i < ctx->nb_streams; i++) +- av_freep(&ctx->streams[i]->priv_data); +- return AVERROR(ENOMEM); + } + + static inline void put_timestamp(AVIOContext *pb, int id, int64_t timestamp) +@@ -1255,11 +1250,19 @@ static int mpeg_mux_end(AVFormatContext *ctx) + stream = ctx->streams[i]->priv_data; + + av_assert0(av_fifo_size(stream->fifo) == 0); +- av_fifo_freep(&stream->fifo); + } + return 0; + } + ++static void mpeg_mux_deinit(AVFormatContext *ctx) ++{ ++ for (int i = 0; i < ctx->nb_streams; i++) { ++ StreamInfo *stream = ctx->streams[i]->priv_data; ++ av_fifo_freep(&stream->fifo); ++ } ++} ++ ++ + #define OFFSET(x) offsetof(MpegMuxContext, x) + #define E AV_OPT_FLAG_ENCODING_PARAM + static const AVOption options[] = { +@@ -1289,6 +1292,7 @@ AVOutputFormat ff_mpeg1system_muxer = { + .write_header = mpeg_mux_init, + .write_packet = mpeg_mux_write_packet, + .write_trailer = mpeg_mux_end, ++ .deinit = mpeg_mux_deinit, + .priv_class = &mpeg_class, + }; + #endif +@@ -1305,6 +1309,7 @@ AVOutputFormat ff_mpeg1vcd_muxer = { + .write_header = mpeg_mux_init, + .write_packet = mpeg_mux_write_packet, + .write_trailer = mpeg_mux_end, ++ .deinit = mpeg_mux_deinit, + .priv_class = &vcd_class, + }; + #endif +@@ -1322,6 +1327,7 @@ AVOutputFormat ff_mpeg2vob_muxer = { + .write_header = mpeg_mux_init, + .write_packet = mpeg_mux_write_packet, + .write_trailer = mpeg_mux_end, ++ .deinit = mpeg_mux_deinit, + .priv_class = &vob_class, + }; + #endif +@@ -1340,6 +1346,7 @@ AVOutputFormat ff_mpeg2svcd_muxer = { + .write_header = mpeg_mux_init, + .write_packet = mpeg_mux_write_packet, + .write_trailer = mpeg_mux_end, ++ .deinit = mpeg_mux_deinit, + .priv_class = &svcd_class, + }; + #endif +diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c +index 2c2334a..f828102 100644 +--- a/libavformat/nutenc.c ++++ b/libavformat/nutenc.c +@@ -1172,7 +1172,7 @@ static int nut_write_trailer(AVFormatContext *s) + write_headers(s, bc); + + ret = avio_open_dyn_buf(&dyn_bc); +- if (ret >= 0 && nut->sp_count) { ++ if (ret >= 0) { + av_assert1(nut->write_index); // sp_count should be 0 if no index is going to be written + write_index(nut, dyn_bc); + put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE); +-- +2.43.0 +