1
0
mirror of https://git.ffmpeg.org/ffmpeg.git synced 2026-10-24 02:09:03 +03:00

checkasm/sw_ops: check for undeclared over-write

Use checkasm's own BUF_RECT() and padded buffer checking to get this
for almost free. The one major issue is that check_*_padded() assumes the
padding is a power of two alignment, which is not an assumption made by
libswscale.

Fix this by explicitly copying over the declared number of over-write bytes
from the reference buffer, before doing the check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Niklas Haas <git@haasn.dev>
This commit is contained in:
Niklas Haas
2026-10-22 20:43:58 +02:00
parent 85b14e60ea
commit 6f22b03151

View File

@@ -158,8 +158,9 @@ static void check_compiled(const Test *test,
static DECLARE_ALIGNED_64(char, src0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
static DECLARE_ALIGNED_64(char, src1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
static DECLARE_ALIGNED_64(char, dst0)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
static DECLARE_ALIGNED_64(char, dst1)[NB_PLANES][LINES][PIXELS * sizeof(uint32_t[4])];
/* All output planes are stacked vertically in a single padded buffer */
static BUF_RECT(uint8_t, dst0, PIXELS * sizeof(uint32_t[4]), NB_PLANES * LINES);
static BUF_RECT(uint8_t, dst1, PIXELS * sizeof(uint32_t[4]), NB_PLANES * LINES);
av_assert0(PIXELS % comp_new->block_size == 0);
for (int p = 0; p < NB_PLANES; p++) {
@@ -186,8 +187,8 @@ static void check_compiled(const Test *test,
}
memcpy(src1, src0, sizeof(src0));
memset(dst0, 0, sizeof(dst0));
memset(dst1, 0, sizeof(dst1));
CLEAR_BUF_RECT(dst0);
CLEAR_BUF_RECT(dst1);
const int read_size = PIXELS * test->pixel_bits_in >> 3;
const int write_size = PIXELS * test->pixel_bits_out >> 3;
@@ -197,7 +198,7 @@ static void check_compiled(const Test *test,
exec.height = exec.slice_h = LINES;
for (int i = 0; i < NB_PLANES; i++) {
exec.in_stride[i] = sizeof(src0[i][0]);
exec.out_stride[i] = sizeof(dst0[i][0]);
exec.out_stride[i] = dst0_stride;
exec.in_bump[i] = exec.in_stride[i] - read_size;
exec.out_bump[i] = exec.out_stride[i] - write_size;
}
@@ -228,7 +229,7 @@ static void check_compiled(const Test *test,
for (int i = 0; i < NB_PLANES; i++) {
exec.in[i] = (void *) src0[i];
exec.out[i] = (void *) dst0[i];
exec.out[i] = dst0 + i * LINES * dst0_stride;
exec.block_size_in[i] = comp_ref->block_size * test->pixel_bits_in >> 3;
exec.block_size_out[i] = comp_ref->block_size * test->pixel_bits_out >> 3;
}
@@ -236,7 +237,7 @@ static void check_compiled(const Test *test,
for (int i = 0; i < NB_PLANES; i++) {
exec.in[i] = (void *) src1[i];
exec.out[i] = (void *) dst1[i];
exec.out[i] = dst1 + i * LINES * dst1_stride;
exec.block_size_in[i] = comp_new->block_size * test->pixel_bits_in >> 3;
exec.block_size_out[i] = comp_new->block_size * test->pixel_bits_out >> 3;
}
@@ -246,28 +247,41 @@ static void check_compiled(const Test *test,
if (!SWS_COMP_TEST(test->planes_out, i))
continue;
/* checkasm_check_padded() assumes a power of two alignment, but our
* overwrite may be an arbitrary number of bytes. Smooth out the
* difference by manually copying over the padding from the reference
* to the output buffer, and extending the checked padding past it. */
const int elem_size = ff_sws_pixel_type_size(test->type_out);
const int over_write = comp_new->over_write[i];
const int padding = (over_write + elem_size - 1) / elem_size + 8;
const int w = write_size / elem_size;
const uint8_t *out_ref = dst0 + i * LINES * dst0_stride;
uint8_t *out_new = exec.out[i];
for (int y = 0; y < LINES; y++) {
memcpy(&out_new[y * dst1_stride + write_size],
&out_ref[y * dst0_stride + write_size], over_write);
}
const char *desc = FMT("%s[%d]", test->name, i);
const int stride = sizeof(dst0[i][0]);
switch (test->type_out) {
case SWS_PIXEL_U8:
checkasm_check(uint8_t, (void *) dst0[i], stride,
(void *) dst1[i], stride,
write_size, LINES, desc);
checkasm_check_padded(uint8_t, out_ref, dst0_stride, out_new, dst1_stride,
w, LINES, desc, 1, 0, padding);
break;
case SWS_PIXEL_U16:
checkasm_check(uint16_t, (void *) dst0[i], stride,
(void *) dst1[i], stride,
write_size >> 1, LINES, desc);
checkasm_check_padded(uint16_t, (void *) out_ref, dst0_stride,
(void *) out_new, dst1_stride,
w, LINES, desc, 1, 0, padding);
break;
case SWS_PIXEL_U32:
checkasm_check(uint32_t, (void *) dst0[i], stride,
(void *) dst1[i], stride,
write_size >> 2, LINES, desc);
checkasm_check_padded(uint32_t, (void *) out_ref, dst0_stride,
(void *) out_new, dst1_stride,
w, LINES, desc, 1, 0, padding);
break;
case SWS_PIXEL_F32:
checkasm_check(float_ulp, (void *) dst0[i], stride,
(void *) dst1[i], stride,
write_size >> 2, LINES, desc, 0);
checkasm_check_padded(float_ulp, (void *) out_ref, dst0_stride,
(void *) out_new, dst1_stride,
w, LINES, desc, 0, 1, 0, padding);
break;
}
}