From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 19BC04B553 for ; Thu, 21 Aug 2025 20:02:28 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 7EF3F6800A8; Thu, 21 Aug 2025 23:02:24 +0300 (EEST) Received: from c1ad6a1ecdc3 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id C0EFF6800A1 for ; Thu, 21 Aug 2025 23:02:22 +0300 (EEST) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] =?utf-8?q?=5BPATCH=5D_WIP=3A_avcodec/sanm=3A_blub?= =?utf-8?b?Yi0xIChQUiAjMjAzMDcp?= X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Manuel Lauss via ffmpeg-devel Reply-To: FFmpeg development discussions and patches Cc: Manuel Lauss Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Message-Id: <20250821200224.7EF3F6800A8@ffbox0-bg.ffmpeg.org> Date: Thu, 21 Aug 2025 23:02:24 +0300 (EEST) Archived-At: List-Archive: List-Post: PR #20307 opened by Manuel Lauss (mlauss2) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20307 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20307.patch >From 81464c509dfece2e6a17f5608c1b904705c8b7fd Mon Sep 17 00:00:00 2001 From: Manuel Lauss Date: Thu, 21 Aug 2025 22:00:32 +0200 Subject: [PATCH] avcodec/sanm: blubb-1 blubb-2 --- libavcodec/sanm.c | 64 +++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/libavcodec/sanm.c b/libavcodec/sanm.c index 4cf1ac5221..bbc3ad9043 100644 --- a/libavcodec/sanm.c +++ b/libavcodec/sanm.c @@ -277,6 +277,7 @@ typedef struct SANMVideoContext { uint16_t *fbuf, *frm0, *frm1, *frm2; uint8_t *stored_frame; uint32_t fbuf_size, frm0_size, frm1_size, frm2_size; + uint32_t stor_size; uint32_t stored_frame_size; uint8_t *rle_buf; @@ -471,9 +472,11 @@ static av_cold int init_buffers(SANMVideoContext *ctx) av_fast_padded_mallocz(&ctx->frm0, &ctx->frm0_size, ctx->buf_size); av_fast_padded_mallocz(&ctx->frm1, &ctx->frm1_size, ctx->buf_size); av_fast_padded_mallocz(&ctx->frm2, &ctx->frm2_size, ctx->buf_size); - if (!ctx->version) + if (!ctx->version) { av_fast_padded_mallocz(&ctx->stored_frame, &ctx->stored_frame_size, ctx->buf_size); + ctx->stor_size = 0; + } if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 || (!ctx->stored_frame && !ctx->version)) { @@ -1660,7 +1663,8 @@ 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 xoff, int yoff) { uint16_t w, h, parm2; uint8_t codec, param; @@ -1669,14 +1673,14 @@ 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) + xoff; + top = bytestream2_get_le16u(gb) + yoff; w = bytestream2_get_le16u(gb); h = bytestream2_get_le16u(gb); bytestream2_skip(gb, 2); parm2 = bytestream2_get_le16u(gb); - if (w < 1 || h < 1 || w > 800 || h > 600 || left > 800 || top > 600 || left + w <= 0 || top + h <= 0) { + if (w < 1 || h < 1 || w > 640 || h > 480 || left > 640 || top > 480 || left + w <= 0 || top + h <= 0) { av_log(ctx->avctx, AV_LOG_WARNING, "ignoring invalid fobj dimensions: c%d %d %d @ %d %d\n", codec, w, h, left, top); @@ -1700,7 +1704,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) if (w > xres || h > yres) return AVERROR_INVALIDDATA; ctx->have_dimensions = 1; - } else if (codec == 37 || codec == 47 || codec == 48) { + } else if (fsc) { /* these codecs work on full frames, trust their dimensions */ xres = w; yres = h; @@ -1716,7 +1720,7 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) xres = w; yres = h; ctx->have_dimensions = 1; - } else if (((xres == 424) && (yres == 260)) || /* RA1 */ + } else if (((xres == 424) && (yres == 260)) || /* RA2 */ ((xres == 320) && (yres == 200)) || /* ft/dig/... */ ((xres == 640) && (yres == 480))) { /* ol/comi/mots... */ ctx->have_dimensions = 1; @@ -1750,6 +1754,10 @@ static int process_frame_obj(SANMVideoContext *ctx, GetByteContext *gb) } } + /* users of codecs>=37 are subversion 2, enforce that for STOR/FTCH */ + if (fsc) + ctx->subversion = 2; + /* clear the main buffer on the first fob */ if (ctx->first_fob) { ctx->first_fob = 0; @@ -1819,41 +1827,25 @@ 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; /* FTCH defines additional x/y offsets */ - if (size != 12) { - if (bytestream2_get_bytes_left(&ctx->gb) < 6) - return AVERROR_INVALIDDATA; + if (size == 6) { bytestream2_skip(&ctx->gb, 2); xoff = bytestream2_get_le16u(&ctx->gb); yoff = bytestream2_get_le16u(&ctx->gb); - } else { - if (bytestream2_get_bytes_left(&ctx->gb) < 12) - return AVERROR_INVALIDDATA; + } else if (size == 12) { bytestream2_skip(&ctx->gb, 4); xoff = bytestream2_get_be32u(&ctx->gb); yoff = bytestream2_get_be32u(&ctx->gb); - } - - 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); + } else + return 1; + if (ctx->stor_size > 0) { /* 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); + bytestream2_init(&gb, ctx->stored_frame, ctx->stor_size); + 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 @@ -2360,8 +2352,10 @@ 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)) { + to_store = 0; return ret; + } have_img = 1; /* STOR: for ANIMv0/1 store the whole FOBJ datablock, as it @@ -2372,12 +2366,12 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *frame, if (to_store) { to_store = 0; if (ctx->subversion < 2) { - if (size + 4 <= ctx->stored_frame_size) { + if (size <= ctx->stored_frame_size) { int pos2 = bytestream2_tell(&ctx->gb); bytestream2_seek(&ctx->gb, pos, SEEK_SET); - *(uint32_t *)(ctx->stored_frame) = size; - bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame + 4, size); + bytestream2_get_bufferu(&ctx->gb, ctx->stored_frame, size); bytestream2_seek(&ctx->gb, pos2, SEEK_SET); + ctx->stor_size = size; } else { av_log(avctx, AV_LOG_ERROR, "FOBJ too large for STOR\n"); ret = AVERROR(ENOMEM); -- 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".