Commit 6de448b6e7 for ffmpeg
commit 6de448b6e72835ef66619faccd29dca5b59ce165
Author: Michael Niedermayer <michael@niedermayer.cc>
Date: Fri Oct 2 06:01:09 2026 +0200
swscale/ops_memcpy: do not clear or copy past the last line
Found during triage of the security report edlOwd4qVGBw.
Fixes: out of array read
Fixes: out of array write
Fixes: negative size memset() / memcpy()
Fixes: orU7yZg5HmsB
Regression since: a151b426f9
Replicated through API
Replicated through UnModified FFmpeg
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/ops_memcpy.c b/libswscale/ops_memcpy.c
index 52ba64b0c3..735006ab18 100644
--- a/libswscale/ops_memcpy.c
+++ b/libswscale/ops_memcpy.c
@@ -49,9 +49,11 @@ static void process(const SwsOpExec *exec, const void *priv,
uint8_t *out = exec->out[i];
const int idx = p->index[i];
const int bytes = x_end * exec->block_size_out[i];
- const int use_loop = exec->out_stride[i] > bytes + SWS_MAX_PADDING;
+ const int use_loop = exec->out_stride[i] < 0 ||
+ exec->out_stride[i] > bytes + SWS_MAX_PADDING;
+ const size_t span = (size_t) (lines - 1) * exec->out_stride[i] + bytes;
if (idx < 0 && !use_loop) {
- memset(out, p->clear_value[i], exec->out_stride[i] * lines);
+ memset(out, p->clear_value[i], span);
} else if (idx < 0) {
for (int y = y_start; y < y_end; y++) {
memset(out, p->clear_value[i], bytes);
@@ -61,7 +63,7 @@ static void process(const SwsOpExec *exec, const void *priv,
av_assert1(exec->out_stride[i] == exec->in_stride[idx]);
continue; /* plane was already ref'd */
} else if (exec->out_stride[i] == exec->in_stride[idx] && !use_loop) {
- memcpy(out, exec->in[idx], exec->out_stride[i] * lines);
+ memcpy(out, exec->in[idx], span);
} else {
const uint8_t *in = exec->in[idx];
for (int y = y_start; y < y_end; y++) {