From fc6e645d8bea0436c19e66ea9096fb99fdb472a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=87=8C=E7=A9=BA=E5=85=88=E7=9F=A5?= <2414106632@qq.com> Date: Thu, 26 Jun 2025 11:38:32 +0800 Subject: [PATCH] fix av_parser_parse2 abort MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 凌空先知 <2414106632@qq.com> --- BUILD.gn | 1 + libavcodec/parser.c | 8 ++++++++ libavformat/dashenc.c | 11 +++++++++++ libavformat/demux.c | 17 +++++++++++++++++ libavformat/flacdec.c | 12 +++++++++++- libavformat/oggparseflac.c | 11 +++++++++++ libavformat/seek.c | 7 +++++++ 7 files changed, 66 insertions(+), 1 deletion(-) diff --git a/BUILD.gn b/BUILD.gn index 460474d2cb..d42d901cc2 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -167,6 +167,7 @@ config("ffmpeg_config") { "-DOHOS_CUSTOM_INFO", "-DOHOS_CAL_DASH_BITRATE", "-DOHOS_AUXILIARY_TRACK", + "-DOHOS_ABORT_FIX", ] if (use_musl) { cflags += [ "-Wno-bool-operation" ] diff --git a/libavcodec/parser.c b/libavcodec/parser.c index 1265d2b6ca..c8922cf05a 100644 --- a/libavcodec/parser.c +++ b/libavcodec/parser.c @@ -162,7 +162,15 @@ int av_parser_parse2(AVCodecParserContext *s, AVCodecContext *avctx, /* WARNING: the returned index can be negative */ index = s->parser->parser_parse(s, avctx, (const uint8_t **) poutbuf, poutbuf_size, buf, buf_size); +#ifdef OHOS_ABORT_FIX + if (index <= -0x20000000) { + av_log(NULL, AV_LOG_ERROR, + "Parser returned an error code %d, which is not allowed.\n", index); + return -0x20000000; + } +#else av_assert0(index > -0x20000000); // The API does not allow returning AVERROR codes +#endif #define FILL(name) if(s->name > 0 && avctx->name <= 0) avctx->name = s->name if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) { FILL(field_order); diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 295b01e225..ddfb68122a 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -2154,9 +2154,20 @@ static int dash_write_packet(AVFormatContext *s, AVPacket *pkt) // Parse the packets only in scenarios where it's needed uint8_t *data; int size; +#ifdef OHOS_ABORT_FIX + int index = av_parser_parse2(os->parser, os->parser_avctx, + &data, &size, pkt->data, pkt->size, + pkt->pts, pkt->dts, pkt->pos); + if (index <= -0x20000000) { + s->pb->error = AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "dash_write_packet returned an error: %d\n", index); + retrun index; + } +#else av_parser_parse2(os->parser, os->parser_avctx, &data, &size, pkt->data, pkt->size, pkt->pts, pkt->dts, pkt->pos); +#endif os->coding_dependency |= os->parser->pict_type != AV_PICTURE_TYPE_I; } diff --git a/libavformat/demux.c b/libavformat/demux.c index e77c9c0d50..136c1796df 100644 --- a/libavformat/demux.c +++ b/libavformat/demux.c @@ -1229,6 +1229,14 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, len = av_parser_parse2(sti->parser, sti->avctx, &out_pkt->data, &out_pkt->size, data, size, pkt->pts, pkt->dts, pkt->pos); +#ifdef OHOS_ABORT_FIX + if (len <= -0x20000000) { + s->pb->error = AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "Parser returned an error: %d\n", len); + ret = AVERROR(EINVAL); + goto fail; + } +#endif pkt->pts = pkt->dts = AV_NOPTS_VALUE; pkt->pos = -1; @@ -1350,8 +1358,17 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) for (unsigned i = 0; i < s->nb_streams; i++) { AVStream *const st = s->streams[i]; FFStream *const sti = ffstream(st); +#ifdef OHOS_ABORT_FIX + if (sti->parser && sti->need_parsing) { + av_log(s, AV_LOG_DEBUG, "Flushing parser for stream %d\n", i); + ret = parse_packet(s, pkt, st->index, 1); + if (ret < 0) + return ret; + } +#else if (sti->parser && sti->need_parsing) parse_packet(s, pkt, st->index, 1); +#endif } /* all remaining packets are now in parse_queue => * really terminate parsing */ diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c index e97b3e133a..7b00775487 100644 --- a/libavformat/flacdec.c +++ b/libavformat/flacdec.c @@ -287,10 +287,20 @@ static av_unused int64_t flac_read_timestamp(AVFormatContext *s, int stream_inde av_assert1(!pkt->size); } } +#ifdef OHOS_ABORT_FIX + int index = av_parser_parse2(parser, ffstream(st)->avctx, + &data, &size, pkt->data, pkt->size, + pkt->pts, pkt->dts, *ppos); + if (index <= -0x20000000) { + s->pb->error = AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "flac_read_timestamp returned an error: %d\n", index); + retrun index; + } +#else av_parser_parse2(parser, ffstream(st)->avctx, &data, &size, pkt->data, pkt->size, pkt->pts, pkt->dts, *ppos); - +#endif av_packet_unref(pkt); if (size) { if (parser->pts != AV_NOPTS_VALUE){ diff --git a/libavformat/oggparseflac.c b/libavformat/oggparseflac.c index fa7459c162..9b6c3310ce 100644 --- a/libavformat/oggparseflac.c +++ b/libavformat/oggparseflac.c @@ -105,9 +105,20 @@ old_flac_header (AVFormatContext * s, int idx) goto fail; parser->flags = PARSER_FLAG_COMPLETE_FRAMES; +#ifdef OHOS_ABORT_FIX + int index = av_parser_parse2(parser, avctx, + &data, &size, os->buf + os->pstart, os->psize, + AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1); + if (index == -0x20000000) { + s->pb->error = AVERROR_INVALIDDATA; + ret = index; + goto fail; + } +#else av_parser_parse2(parser, avctx, &data, &size, os->buf + os->pstart, os->psize, AV_NOPTS_VALUE, AV_NOPTS_VALUE, -1); +#endif av_parser_close(parser); diff --git a/libavformat/seek.c b/libavformat/seek.c index b3bc15f597..b65359070c 100644 --- a/libavformat/seek.c +++ b/libavformat/seek.c @@ -446,6 +446,13 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, if (ts_min == AV_NOPTS_VALUE) { pos_min = si->data_offset; ts_min = read_timestamp(s, stream_index, &pos_min, INT64_MAX, read_timestamp_func); +#ifdef OHOS_ABORT_FIX + if (ts_min == -0x20000000) { + s->pb->error = AVERROR_INVALIDDATA; + av_log(s, AV_LOG_ERROR, "read_timestamp failed at the beginning\n") + return -1; + } +#endif if (ts_min == AV_NOPTS_VALUE) return -1; }