[FFmpeg-devel] [PATCH] VMD demuxer: precedence bug makes failed reads look like success (PR #21165)

2025-12-10 Thread ruikai via ffmpeg-devel
PR #21165 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21165
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21165.patch

In `libavformat/sierravmd.c (vmd_read_header)`, the header read check was 
written as:

```
if ((ret = ffio_read_size(pb, vmd->vmd_header, VMD_HEADER_SIZE) < 0))
return ret;
```

Due to operator precedence, this stores the boolean result of the comparison 
into ret, so a failed read (negative return) becomes `ret = 1,` which is 
treated as success. 
`avformat_open_input() `then completes with zero streams and uninitialized 
state, letting the demuxer proceed into `vmd_read_packet()` with bogus tables.

We have not reported this as a security issue because we did not demonstrate a 
ground-truth crash in validation, though it has an interesting possibility as 
an OOB primitive.

Found-by: Pwno


>From d158e8605cdfcdbd973bddbed52fcc511e590a88 Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Thu, 11 Dec 2025 06:27:48 +
Subject: [PATCH] VMD demuxer: precedence bug makes failed reads look like
 success

---
 libavformat/sierravmd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/sierravmd.c b/libavformat/sierravmd.c
index bb1d1c5df7..2519756533 100644
--- a/libavformat/sierravmd.c
+++ b/libavformat/sierravmd.c
@@ -103,7 +103,7 @@ static int vmd_read_header(AVFormatContext *s)
 
 /* fetch the main header, including the 2 header length bytes */
 avio_seek(pb, 0, SEEK_SET);
-if ((ret = ffio_read_size(pb, vmd->vmd_header, VMD_HEADER_SIZE) < 0))
+if ((ret = ffio_read_size(pb, vmd->vmd_header, VMD_HEADER_SIZE)) < 0)
 return ret;
 
 width = AV_RL16(&vmd->vmd_header[12]);
-- 
2.49.1

___
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]


[FFmpeg-devel] [PATCH] avfilter/drawvg: limit recursion depth in VGS parser (PR #21151)

2025-12-09 Thread ruikai via ffmpeg-devel
PR #21151 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21151
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21151.patch

Prevents stack overflow with deeply nested repeat/if/proc blocks.

Originally reported via ffmpeg-security; this patch incorporates feedback from 
Kacper Michajlow.


>From 1178b51f2ae88ddd4045561b98f4030eb08a531a Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Wed, 10 Dec 2025 01:41:14 +
Subject: [PATCH] avfilter/drawvg: limit recursion depth in VGS parser

Prevents stack overflow with deeply nested repeat/if/proc blocks.
---
 libavfilter/vf_drawvg.c | 28 +++-
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/libavfilter/vf_drawvg.c b/libavfilter/vf_drawvg.c
index 5d3008084c..97e5583366 100644
--- a/libavfilter/vf_drawvg.c
+++ b/libavfilter/vf_drawvg.c
@@ -242,6 +242,8 @@ struct VGSParameter {
 // for the arguments.
 #define MAX_PROC_ARGS (MAX_COMMAND_PARAMS - 2)
 
+#define VGS_MAX_RECURSION_DEPTH 1024
+
 // Definition of each command.
 
 struct VGSCommandSpec {
@@ -435,6 +437,7 @@ struct VGSParser {
 
 const char **proc_names;
 int proc_names_count;
+int depth; ///< Current recursion depth while parsing subprograms.
 
 // Store the variable names for the default ones (from `vgs_default_vars`)
 // and the variables created with `setvar`.
@@ -1232,6 +1235,7 @@ static void vgs_parser_init(struct VGSParser *parser, 
const char *source) {
 
 parser->proc_names = NULL;
 parser->proc_names_count = 0;
+parser->depth = 0;
 
 memset(parser->var_names, 0, sizeof(parser->var_names));
 for (int i = 0; i < VAR_U0; i++)
@@ -1264,11 +1268,20 @@ static int vgs_parse(
 int subprogram
 ) {
 struct VGSParserToken token;
+int ret = 0;
 
 memset(program, 0, sizeof(*program));
 
+parser->depth++;
+if (parser->depth > VGS_MAX_RECURSION_DEPTH) {
+av_log(log_ctx, AV_LOG_ERROR,
+   "Exceeded maximum drawvg block nesting depth (%d)\n",
+   VGS_MAX_RECURSION_DEPTH);
+ret = AVERROR(EINVAL);
+goto out;
+}
+
 for (;;) {
-int ret;
 const struct VGSCommandSpec *cmd;
 
 ret = vgs_parser_next_token(log_ctx, parser, &token, 1);
@@ -1286,7 +1299,7 @@ static int vgs_parse(
 FFSWAP(int, program->proc_names_count, 
parser->proc_names_count);
 }
 
-return 0;
+goto out;
 
 case TOKEN_WORD:
 // The token must be a valid command.
@@ -1304,21 +1317,26 @@ static int vgs_parse(
 if (!subprogram)
 goto invalid_token;
 
-return 0;
+goto out;
 
 default:
 goto invalid_token;
 }
 }
 
-return AVERROR_BUG; /* unreachable */
+ret = AVERROR_BUG; /* unreachable */
+goto out;
 
 invalid_token:
 vgs_log_invalid_token(log_ctx, parser, &token, "Expected command.");
 
 fail:
 vgs_free(program);
-return AVERROR(EINVAL);
+ret = AVERROR(EINVAL);
+
+out:
+parser->depth--;
+return ret;
 }
 
 /*
-- 
2.49.1

___
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]


[FFmpeg-devel] [PATCH] avformat/mpegts: bounds-check JPEG-XS header_size before padding (PR #21196)

2025-12-14 Thread ruikai via ffmpeg-devel
PR #21196 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21196
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21196.patch

Regression since: 536475ea05.

The JPEG-XS PES path trusted header_size from the payload and advanced
pkt->data/pkt->size without validation, so the trailing memset could
write out of bounds when header_size > pkt->size. Reject such packets,
marking them corrupt and returning an error to avoid the OOB write.

Repro (ASan):
ASAN_OPTIONS=halt_on_error=1:detect_leaks=0 \
./ffmpeg -v debug -nostdin -i poc-jpegxs.ts -copy_unknown -map 0 \
 -c copy -f null /dev/null

Crash in new_pes_packet memset on crafted TS with stream_id 0xbd,
stream_type 0x32, header_size 0xFF00, payload starting with jxes.

Found-by: Pwno


>From 91385c6417b60d2d609bceb6ccab3da28070a263 Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Sun, 14 Dec 2025 12:26:37 -0500
Subject: [PATCH] avformat/mpegts: bounds-check JPEG-XS header_size before
 padding

Regression since: 536475ea05.

The JPEG-XS PES path trusted header_size from the payload and advanced
pkt->data/pkt->size without validation, so the trailing memset could
write out of bounds when header_size > pkt->size. Reject such packets,
marking them corrupt and returning an error to avoid the OOB write.

Repro (ASan):
ASAN_OPTIONS=halt_on_error=1:detect_leaks=0   ./ffmpeg -v debug -nostdin -i 
poc-jpegxs.ts -copy_unknown -map 0   -c copy -f null /dev/null

Crash in new_pes_packet memset on crafted TS with stream_id 0xbd,
stream_type 0x32, header_size 0xFF00, payload starting with jxes.

Found-by: Pwno
---
 libavformat/mpegts.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c
index fb1dcd11be..7c19abaf76 100644
--- a/libavformat/mpegts.c
+++ b/libavformat/mpegts.c
@@ -1035,6 +1035,13 @@ static int new_pes_packet(PESContext *pes, AVPacket *pkt)
 pkt->size >= 8 && memcmp(pkt->data + 4, "jxes", 4) == 0)
 {
 uint32_t header_size = AV_RB32(pkt->data);
+if (header_size > pkt->size) {
+av_log(pes->stream, AV_LOG_WARNING,
+   "Invalid JPEG-XS header size %"PRIu32" > packet size %d\n",
+   header_size, pkt->size);
+pes->flags |= AV_PKT_FLAG_CORRUPT;
+return AVERROR_INVALIDDATA;
+}
 pkt->data += header_size;
 pkt->size -= header_size;
 }
-- 
2.49.1

___
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]


[FFmpeg-devel] [PATCH] avcodec/fflcms2: reject extended TRCs in ICC generator (PR #21180)

2025-12-12 Thread ruikai via ffmpeg-devel
PR #21180 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21180
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21180.patch

fflcms2 caches tone curves in an array indexed by
AVColorTransferCharacteristic values up to AVCOL_TRC_NB. After the
introduction of extended transfer characteristics (e.g. Panasonic
V-Log with value 256), get_curve() could be called with such values
and attempt to index s->curves[trc] out of bounds when generating
ICC profiles.

Restrict get_curve() to base TRC values and return
AVERROR_PATCHWELCOME for any transfer characteristic greater than or
equal to AVCOL_TRC_NB. This avoids out-of-bounds accesses for
extended TRCs while leaving the behavior for supported base TRCs
unchanged.

Repro on x86_64 with clang+ASan, lcms2 enabled, at aeb9b19ebc:

ASAN_OPTIONS=detect_leaks=0 ./ffmpeg -v error -f lavfi -i 
testsrc2=size=16x16:rate=1 -frames:v 1 -vf setparams=color_trc=vlog,iccgen -f 
null -

This triggers an ASan heap-buffer-overflow in get_curve(), reading
s->curves[256] and reporting roughly 237 * 8 = 1896 bytes of
out-of-bounds heap data before the function returns
AVERROR_PATCHWELCOME for V-Log.

Impact: denial of service via crafted ICC-generation filtergraphs that
use extended transfer characteristics (e.g. setparams=color_trc=vlog
followed by iccgen) on builds with lcms2 and Panasonic V-Log support
enabled.

Regression since: aeb9b19ebc
Found-by: Pwno


>From 53c644e84783e829ff103adbab6b189be733360c Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Fri, 12 Dec 2025 13:44:55 -0500
Subject: [PATCH] avcodec/fflcms2: reject extended TRCs in ICC generator

fflcms2 caches tone curves in an array indexed by
AVColorTransferCharacteristic values up to AVCOL_TRC_NB. After the
introduction of extended transfer characteristics (e.g. Panasonic
V-Log with value 256), get_curve() could be called with such values
and attempt to index s->curves[trc] out of bounds when generating
ICC profiles.

Restrict get_curve() to base TRC values and return
AVERROR_PATCHWELCOME for any transfer characteristic greater than or
equal to AVCOL_TRC_NB. This avoids out-of-bounds accesses for
extended TRCs while leaving the behavior for supported base TRCs
unchanged.

Repro on x86_64 with clang+ASan, lcms2 enabled, at aeb9b19ebc:

ASAN_OPTIONS=detect_leaks=0 ./ffmpeg -v error -f lavfi -i 
testsrc2=size=16x16:rate=1 -frames:v 1 -vf setparams=color_trc=vlog,iccgen -f 
null -

This triggers an ASan heap-buffer-overflow in get_curve(), reading
s->curves[256] and reporting roughly 237 * 8 = 1896 bytes of
out-of-bounds heap data before the function returns
AVERROR_PATCHWELCOME for V-Log.

Impact: denial of service via crafted ICC-generation filtergraphs that
use extended transfer characteristics (e.g. setparams=color_trc=vlog
followed by iccgen) on builds with lcms2 and Panasonic V-Log support
enabled.

Regression since: aeb9b19ebc
Found-by: Pwno
---
 libavcodec/fflcms2.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c
index 3c7f3dc07f..1ade9cf298 100644
--- a/libavcodec/fflcms2.c
+++ b/libavcodec/fflcms2.c
@@ -50,7 +50,11 @@ void ff_icc_context_uninit(FFIccContext *s)
 static int get_curve(FFIccContext *s, enum AVColorTransferCharacteristic trc,
  cmsToneCurve **out_curve)
 {
-if ((unsigned)trc < AVCOL_TRC_NB && s->curves[trc])
+/* Only base TRCs are cached here; extended TRCs aren't supported yet. */
+if ((unsigned)trc >= AVCOL_TRC_NB)
+return AVERROR_PATCHWELCOME;
+
+if (s->curves[trc])
 goto done;
 
 switch (trc) {
@@ -125,7 +129,6 @@ static int get_curve(FFIccContext *s, enum 
AVColorTransferCharacteristic trc,
 case AVCOL_TRC_BT1361_ECG:
 case AVCOL_TRC_SMPTE2084:
 case AVCOL_TRC_ARIB_STD_B67:
-case AVCOL_TRC_V_LOG:
 return AVERROR_PATCHWELCOME;
 
 default:
-- 
2.49.1

___
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]


[FFmpeg-devel] [PATCH] avcodec/vulkan: fix DPX unpack offset (PR #21181)

2025-12-12 Thread ruikai via ffmpeg-devel
PR #21181 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21181
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21181.patch

The DPX Vulkan unpack shader computes a word offset as

uint off = (line_off + pix_off >> 5);

Due to GLSL operator precedence this is evaluated as
line_off + (pix_off >> 5) rather than (line_off + pix_off) >> 5.
Since line_off is in bits while off is a 32-bit word index,
scanlines beyond y=0 use an inflated offset and the shader reads
past the end of the DPX slice buffer.

Parenthesize the expression so that the sum is shifted as intended:

uint off = (line_off + pix_off) >> 5;

This corrects the unpacked data and removes the CRC mismatch
observed between the software and Vulkan DPX decoders for
mispacked 12-bit DPX samples. The GPU OOB read itself is only
observable indirectly via this corruption since it occurs inside
the shader.

Repro on x86_64 with Vulkan/llvmpipe (531ce713a0e8):

./configure --cc=clang --disable-optimizations --disable-stripping \
--enable-debug=3 --disable-doc --disable-ffplay \
--enable-vulkan --enable-libshaderc \
--enable-hwaccel=dpx_vulkan \
--extra-cflags='-fsanitize=address -fno-omit-frame-pointer' \
--extra-ldflags='-fsanitize=address' && make

VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.json

PoC: packed 12-bit DPX with the packing flag cleared so the unpack
shader runs (4x64 gbrp12le), e.g. poc12_packed0.dpx.

Software decode:

./ffmpeg -v error -i poc12_packed0.dpx -f framecrc -
-> 0, ..., 1536, 0x26cf81c2

Vulkan hwaccel decode:

VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.json \
./ffmpeg -v error -init_hw_device vulkan \
-hwaccel vulkan -hwaccel_output_format vulkan \
-i poc12_packed0.dpx \
-vf hwdownload,format=gbrp12le -f framecrc -
-> 0, ..., 1536, 0x71e10a51

The only difference between the two runs is the Vulkan unpack
shader, and the stable CRC mismatch indicates that it is reading
past the intended DPX slice region.

Regression since: 531ce713a0e8
Found-by: Pwno


>From 6bb19e6c869512f0355a71aeb032d090b9f29061 Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Fri, 12 Dec 2025 13:51:12 -0500
Subject: [PATCH] avcodec/vulkan: fix DPX unpack offset

The DPX Vulkan unpack shader computes a word offset as

uint off = (line_off + pix_off >> 5);

Due to GLSL operator precedence this is evaluated as
line_off + (pix_off >> 5) rather than (line_off + pix_off) >> 5.
Since line_off is in bits while off is a 32-bit word index,
scanlines beyond y=0 use an inflated offset and the shader reads
past the end of the DPX slice buffer.

Parenthesize the expression so that the sum is shifted as intended:

uint off = (line_off + pix_off) >> 5;

This corrects the unpacked data and removes the CRC mismatch
observed between the software and Vulkan DPX decoders for
mispacked 12-bit DPX samples. The GPU OOB read itself is only
observable indirectly via this corruption since it occurs inside
the shader.

Repro on x86_64 with Vulkan/llvmpipe (531ce713a0e8):

./configure --cc=clang --disable-optimizations --disable-stripping \
--enable-debug=3 --disable-doc --disable-ffplay \
--enable-vulkan --enable-libshaderc \
--enable-hwaccel=dpx_vulkan \
--extra-cflags='-fsanitize=address -fno-omit-frame-pointer' \
--extra-ldflags='-fsanitize=address' && make

VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.json

PoC: packed 12-bit DPX with the packing flag cleared so the unpack
shader runs (4x64 gbrp12le), e.g. poc12_packed0.dpx.

Software decode:

./ffmpeg -v error -i poc12_packed0.dpx -f framecrc -
-> 0, ..., 1536, 0x26cf81c2

Vulkan hwaccel decode:

VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/lvp_icd.json \
./ffmpeg -v error -init_hw_device vulkan \
-hwaccel vulkan -hwaccel_output_format vulkan \
-i poc12_packed0.dpx \
-vf hwdownload,format=gbrp12le -f framecrc -
-> 0, ..., 1536, 0x71e10a51

The only difference between the two runs is the Vulkan unpack
shader, and the stable CRC mismatch indicates that it is reading
past the intended DPX slice region.

Regression since: 531ce713a0e8
Found-by: Pwno
---
 libavcodec/vulkan/dpx_unpack.comp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/vulkan/dpx_unpack.comp 
b/libavcodec/vulkan/dpx_unpack.comp
index b04ce5ddc6..b5ca2cf509 100644
--- a/libavcodec/vulkan/dpx_unpack.comp
+++ b/libavcodec/vulkan/dpx_unpack.comp
@@ -51,7 +51,7 @@ i16vec4 parse_packed_in_32(ivec2 pos, int stride)
 uint line_off = pos.y*line_size;
 uint pix_off = pos.x*BITS_PER_COMP*COMPONENTS;
 
-uint off = (line_off + pix_off >> 5);
+uint off = (line_off + pix_off) >> 5;
 uint bit = pix_off & 0x1f;
 
 uint32_t d0 = read_data(off + 0);
-- 
2.49.1

___
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to ffmpeg-dev

[FFmpeg-devel] [PATCH] avcodec/libsvtjpegxsdec: bound chunk copies and map errors (PR #21198)

2025-12-14 Thread ruikai via ffmpeg-devel
PR #21198 opened by ruikai
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21198
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21198.patch

Regression since: 08db850159

Chunked JPEG-XS decode returned positive libsvtjpegxs errors directly,
so FFmpeg treated failures as “bytes consumed” and kept calling the
decoder with a stale buffer_filled_len. If a libsvtjpegxs error occurred
after the chunk buffer reached frame_size, the next call underflowed
frame_size - buffer_filled_len and memcpy wrote out of bounds.

Fix by translating libsvtjpegxs errors to AVERROR codes, guarding the
chunk memcpy with strict bounds, and resetting buffer_filled_len on
decoder errors so fragmented JPEG-XS input remains safe instead of
crashing.

Repro (ASan):
1) Build with ASan + --enable-libsvtjpegxs.
2) Generate a valid JPEG-XS stream and split into chunks:
   - 64x64 yuv420p 8-bit -> sample.jxs
   - chunk1 = first 400 bytes; chunk2 = 2500 zero bytes; chunk3 = 1 byte 0xff
   - chunks.ffconcat:
 ffconcat version 1.0
 file chunk1.jxs
 duration 0.04
 file chunk2.jxs
 duration 0.04
 file chunk3.jxs
 duration 0.04
3) Run:
   LD_LIBRARY_PATH=/usr/local/lib ASAN_OPTIONS=detect_leaks=0./ffmpeg -v 
debug -safe 0 -protocol_whitelist file  -f concat -i chunks.ffconcat  
-c:v libsvtjpegxs -f null -

ASan: AddressSanitizer: negative-size-param in memcpy
  at libavcodec/libsvtjpegxsdec.c:161
  libsvtjpegxs returns err=-2147471359 (positive), FFmpeg continues, next
  packet underflows bytes_to_copy and triggers the OOB write.

Found-by: Pwno


From 1e53dadf8c629f7530e465d90c7e71a029370fe8 Mon Sep 17 00:00:00 2001
From: Ruikai Peng 
Date: Sun, 14 Dec 2025 14:29:05 -0500
Subject: [PATCH] avcodec/libsvtjpegxsdec: bound chunk copies and map errors
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Regression since: 08db850159

Chunked JPEG-XS decode returned positive libsvtjpegxs errors directly,
so FFmpeg treated failures as “bytes consumed” and kept calling the
decoder with a stale buffer_filled_len. If a libsvtjpegxs error occurred
after the chunk buffer reached frame_size, the next call underflowed
frame_size - buffer_filled_len and memcpy wrote out of bounds.

Fix by translating libsvtjpegxs errors to AVERROR codes, guarding the
chunk memcpy with strict bounds, and resetting buffer_filled_len on
decoder errors so fragmented JPEG-XS input remains safe instead of
crashing.

Repro (ASan):
1) Build with ASan + --enable-libsvtjpegxs.
2) Generate a valid JPEG-XS stream and split into chunks:
   - 64x64 yuv420p 8-bit -> sample.jxs
   - chunk1 = first 400 bytes; chunk2 = 2500 zero bytes; chunk3 = 1 byte 0xff
   - chunks.ffconcat:
 ffconcat version 1.0
 file chunk1.jxs
 duration 0.04
 file chunk2.jxs
 duration 0.04
 file chunk3.jxs
 duration 0.04
3) Run:
   LD_LIBRARY_PATH=/usr/local/lib ASAN_OPTIONS=detect_leaks=0./ffmpeg -v 
debug -safe 0 -protocol_whitelist file  -f concat -i chunks.ffconcat  
-c:v libsvtjpegxs -f null -

ASan: AddressSanitizer: negative-size-param in memcpy
  at libavcodec/libsvtjpegxsdec.c:161
  libsvtjpegxs returns err=-2147471359 (positive), FFmpeg continues, next
  packet underflows bytes_to_copy and triggers the OOB write.

Found-by: Pwno
---
 libavcodec/libsvtjpegxsdec.c | 33 -
 1 file changed, 24 insertions(+), 9 deletions(-)

diff --git a/libavcodec/libsvtjpegxsdec.c b/libavcodec/libsvtjpegxsdec.c
index 45d9134cd4..bb2625eca5 100644
--- a/libavcodec/libsvtjpegxsdec.c
+++ b/libavcodec/libsvtjpegxsdec.c
@@ -51,6 +51,15 @@ typedef struct SvtJpegXsDecodeContext {
 int proxy_mode;
 } SvtJpegXsDecodeContext;
 
+static av_always_inline int map_svt_err(SvtJxsErrorType_t err)
+{
+if (err == SvtJxsErrorDecoderConfigChange)
+return AVERROR_INPUT_CHANGED;
+if (err != SvtJxsErrorNone)
+return AVERROR_EXTERNAL;
+return 0;
+}
+
 static int set_pix_fmt(AVCodecContext* avctx, const svt_jpeg_xs_image_config_t 
*config)
 {
 int ret = 0;
@@ -109,7 +118,7 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, 
AVFrame* picture, int* g
 avpkt->data, avpkt->size, NULL, &svt_dec->frame_size, 1 /*quick 
search*/, svt_dec->decoder.proxy_mode);
 if (err) {
 av_log(avctx, AV_LOG_ERROR, 
"svt_jpeg_xs_decoder_get_single_frame_size_with_proxy failed, err=%d\n", err);
-return err;
+return map_svt_err(err);
 }
 if (avpkt->size < svt_dec->frame_size) {
 svt_dec->chunk_decoding = 1;
@@ -129,7 +138,7 @@ static int svt_jpegxs_dec_decode(AVCodecContext* avctx, 
AVFrame* picture, int* g
&svt_dec->decoder, avpkt->data, 
avpkt->size, &svt_dec->config);
 if (err) {
 av_log(avctx, AV_LOG_ERROR, "svt_jpeg_xs_decoder_init failed, 
err=%d\n", err);
-return err;
+return map_svt_err(err);
 }