From: michaelni via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> To: ffmpeg-devel@ffmpeg.org Cc: michaelni <code@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH] ff-tmp-sanm-unhack (PR #20306) Date: Thu, 21 Aug 2025 20:21:57 +0300 (EEST) Message-ID: <20250821172157.CD36068D7E4@ffbox0-bg.ffmpeg.org> (raw) PR #20306 opened by michaelni URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20306 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20306.patch Remove some pointers into freed buffers Fixes BIGSLEEP-440183164 From fbc1d9dca1aa30ac5e2c63c295652c4b1f54d7be Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <michael@niedermayer.cc> Date: Thu, 21 Aug 2025 18:40:26 +0200 Subject: [PATCH 1/3] avcodec/sanm: Replace impossible bitstream check by assert the space left and size have already been cross checked by the caller Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/sanm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index e4308af647..1495da2a1e 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1832,8 +1832,7 @@ static int process_ftch(SANMVideoContext *ctx, int size) xoff = bytestream2_get_le16u(&ctx->gb); yoff = bytestream2_get_le16u(&ctx->gb); } else { - if (bytestream2_get_bytes_left(&ctx->gb) < 12) - return AVERROR_INVALIDDATA; + av_assert0(bytestream2_get_bytes_left(&ctx->gb) >= 12); bytestream2_skip(&ctx->gb, 4); xoff = bytestream2_get_be32u(&ctx->gb); yoff = bytestream2_get_be32u(&ctx->gb); -- 2.49.1 From e7b08e87c6f5205bc4c6355ab7138a2ae0a8de17 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <michael@niedermayer.cc> Date: Thu, 21 Aug 2025 18:59:36 +0200 Subject: [PATCH 2/3] avcodec/sanm: Remove left/top adjustment hack Fixes: write after free Fixes: BIGSLEEP-440183164/process_ftch.anim Found-by: Google Big Sleep Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/sanm.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 1495da2a1e..83e0eb7241 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1660,7 +1660,7 @@ static int old_codec48(SANMVideoContext *ctx, int width, int height) return 0; } -static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) +static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb, int extraleft, int extratop) { uint16_t w, h, parm2; uint8_t codec, param; @@ -1669,8 +1669,8 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) codec = bytestream2_get_byteu(gb); param = bytestream2_get_byteu(gb); - left = bytestream2_get_le16u(gb); - top = bytestream2_get_le16u(gb); + left = bytestream2_get_le16u(gb) + extraleft; + top = bytestream2_get_le16u(gb) + extratop; w = bytestream2_get_le16u(gb); h = bytestream2_get_le16u(gb); bytestream2_skip(gb, 2); @@ -1820,7 +1820,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) static int process_ftch(SANMVideoContext *ctx, int size) { uint8_t *sf = ctx->stored_frame; - int xoff, yoff, left, top, ret; + int xoff, yoff, ret; GetByteContext gb; uint32_t sz; @@ -1841,18 +1841,10 @@ static int process_ftch(SANMVideoContext *ctx, int size) sz = *(uint32_t *)(sf + 0); if ((sz > 0) && (sz <= ctx->stored_frame_size - 4)) { /* add the FTCH offsets to the left/top values of the stored FOBJ */ - left = av_le2ne16(*(int16_t *)(sf + 4 + 2)); - top = av_le2ne16(*(int16_t *)(sf + 4 + 4)); - *(int16_t *)(sf + 4 + 2) = av_le2ne16(left + xoff); - *(int16_t *)(sf + 4 + 4) = av_le2ne16(top + yoff); /* decode the stored FOBJ */ bytestream2_init(&gb, sf + 4, sz); - ret = process_frame_obj(ctx, &gb); - - /* now restore the original left/top values again */ - *(int16_t *)(sf + 4 + 2) = av_le2ne16(left); - *(int16_t *)(sf + 4 + 4) = av_le2ne16(top); + ret = process_frame_obj(ctx, &gb, xoff, yoff); } else { /* this happens a lot in RA1: The individual files are meant to * be played in sequence, with some referencing objects STORed @@ -2359,7 +2351,7 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, case MKBETAG('F', 'O', 'B', 'J'): if (size < 16) return AVERROR_INVALIDDATA; - if (ret = process_frame_obj(ctx, &ctx->gb)) + if (ret = process_frame_obj(ctx, &ctx->gb, 0, 0)) return ret; have_img = 1; -- 2.49.1 From 36ca6798358686268093473cbbcb3e706d8ad2c2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <michael@niedermayer.cc> Date: Thu, 21 Aug 2025 19:06:03 +0200 Subject: [PATCH 3/3] avcodec/sanm: Eliminate reference into reallocated frame AFAIK the original decoder uses the frame buffers in very strange ways our implementation seems to mimic that and that results in the bitstream input to point into a frame buffer while code then parses that and potentially reallocates the frame buffer leaving pointers hanging into dealllocated space This simply uses a temporary buffer Fixes: Writing into freed buffers Fixes: BIGSLEEP-440183164/old_codec21.anim Fixes: BIGSLEEP-440183164/old_codec4.anim Found-by: Google Big Sleep Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> --- libavcodec/sanm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 83e0eb7241..b1a0d05ddc 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -1843,8 +1843,13 @@ static int process_ftch(SANMVideoContext *ctx, int size) /* add the FTCH offsets to the left/top values of the stored FOBJ */ /* decode the stored FOBJ */ - bytestream2_init(&gb, sf + 4, sz); + uint8_t *bitstream = av_malloc(sz + AV_INPUT_BUFFER_PADDING_SIZE); + if (!bitstream) + return AVERROR(ENOMEM); + memcpy(bitstream, sf + 4, sz); + bytestream2_init(&gb, bitstream, sz); ret = process_frame_obj(ctx, &gb, xoff, yoff); + av_free(bitstream); } else { /* this happens a lot in RA1: The individual files are meant to * be played in sequence, with some referencing objects STORed -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2025-08-21 17:22 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20250821172157.CD36068D7E4@ffbox0-bg.ffmpeg.org \ --to=ffmpeg-devel@ffmpeg.org \ --cc=code@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git