This backports similar functionality from dav1d, from commits
35d1d011fda4a92bcaf42d30ed137583b27d7f6d and
d130da9c315d5a1d3968d278bbee2238ad9051e7.

This allows detecting writes out of bounds, on all 4 sides of
the intended destination rectangle.

The bounds checking also can optionally allow small overwrites
(up to a specified alignment), while still checking for larger
overwrites past the intended allowed region.
---
 tests/checkasm/checkasm.c | 89 ++++++++++++++++++++++++++++++---------
 tests/checkasm/checkasm.h | 55 ++++++++++++++++++++----
 2 files changed, 116 insertions(+), 28 deletions(-)

diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index c6d641c52b..a5b862fe52 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -1168,37 +1168,88 @@ void checkasm_report(const char *name, ...)
     }
 }
 
+static int check_err(const char *file, int line,
+                     const char *name, int w, int h,
+                     int *err)
+{
+    if (*err)
+        return 0;
+    if (!checkasm_fail_func("%s:%d", file, line))
+        return 1;
+    *err = 1;
+    fprintf(stderr, "%s (%dx%d):\n", name, w, h);
+    return 0;
+}
+
 #define DEF_CHECKASM_CHECK_FUNC(type, fmt) \
 int checkasm_check_##type(const char *file, int line, \
                           const type *buf1, ptrdiff_t stride1, \
                           const type *buf2, ptrdiff_t stride2, \
-                          int w, int h, const char *name) \
+                          int w, int h, const char *name, \
+                          int align_w, int align_h, \
+                          int padding) \
 { \
+    int aligned_w = (w + align_w - 1) & ~(align_w - 1); \
+    int aligned_h = (h + align_h - 1) & ~(align_h - 1); \
+    int err = 0; \
     int y = 0; \
     stride1 /= sizeof(*buf1); \
     stride2 /= sizeof(*buf2); \
     for (y = 0; y < h; y++) \
         if (memcmp(&buf1[y*stride1], &buf2[y*stride2], w*sizeof(*buf1))) \
             break; \
-    if (y == h) \
-        return 0; \
-    if (!checkasm_fail_func("%s:%d", file, line)) \
-        return 1; \
-    fprintf(stderr, "%s:\n", name); \
-    while (h--) { \
-        for (int x = 0; x < w; x++) \
-            fprintf(stderr, " " fmt, buf1[x]); \
-        fprintf(stderr, "    "); \
-        for (int x = 0; x < w; x++) \
-            fprintf(stderr, " " fmt, buf2[x]); \
-        fprintf(stderr, "    "); \
-        for (int x = 0; x < w; x++) \
-            fprintf(stderr, "%c", buf1[x] != buf2[x] ? 'x' : '.'); \
-        buf1 += stride1; \
-        buf2 += stride2; \
-        fprintf(stderr, "\n"); \
+    if (y != h) { \
+        if (check_err(file, line, name, w, h, &err)) \
+            return 1; \
+        for (y = 0; y < h; y++) { \
+            for (int x = 0; x < w; x++) \
+                fprintf(stderr, " " fmt, buf1[x]); \
+            fprintf(stderr, "    "); \
+            for (int x = 0; x < w; x++) \
+                fprintf(stderr, " " fmt, buf2[x]); \
+            fprintf(stderr, "    "); \
+            for (int x = 0; x < w; x++) \
+                fprintf(stderr, "%c", buf1[x] != buf2[x] ? 'x' : '.'); \
+            buf1 += stride1; \
+            buf2 += stride2; \
+            fprintf(stderr, "\n"); \
+        } \
+        buf1 -= h*stride1; \
+        buf2 -= h*stride2; \
     } \
-    return 1; \
+    for (y = -padding; y < 0; y++) \
+        if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+                   (w + 2*padding)*sizeof(*buf1))) { \
+            if (check_err(file, line, name, w, h, &err)) \
+                return 1; \
+            fprintf(stderr, " overwrite above\n"); \
+            break; \
+        } \
+    for (y = aligned_h; y < aligned_h + padding; y++) \
+        if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+                   (w + 2*padding)*sizeof(*buf1))) { \
+            if (check_err(file, line, name, w, h, &err)) \
+                return 1; \
+            fprintf(stderr, " overwrite below\n"); \
+            break; \
+        } \
+    for (y = 0; y < h; y++) \
+        if (memcmp(&buf1[y*stride1 - padding], &buf2[y*stride2 - padding], \
+                   padding*sizeof(*buf1))) { \
+            if (check_err(file, line, name, w, h, &err)) \
+                return 1; \
+            fprintf(stderr, " overwrite left\n"); \
+            break; \
+        } \
+    for (y = 0; y < h; y++) \
+        if (memcmp(&buf1[y*stride1 + aligned_w], &buf2[y*stride2 + aligned_w], 
\
+                   padding*sizeof(*buf1))) { \
+            if (check_err(file, line, name, w, h, &err)) \
+                return 1; \
+            fprintf(stderr, " overwrite right\n"); \
+            break; \
+        } \
+    return err; \
 }
 
 DEF_CHECKASM_CHECK_FUNC(uint8_t,  "%02x")
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 852d6fca64..ca7cfac3f7 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -375,11 +375,30 @@ typedef struct CheckasmPerf {
 #define PERF_STOP(t)   while(0)
 #endif
 
+#define BUF_RECT(type, name, w, h) \
+    LOCAL_ALIGNED_32(type, name##_buf, [((h)+32)*(FFALIGN(w,64)+64) + 64]); \
+    av_unused ptrdiff_t name##_stride = sizeof(type)*(FFALIGN(w,64)+64); \
+    av_unused int name##_buf_h = (h)+32; \
+    type *name = name##_buf + (FFALIGN(w,64)+64)*16 + 64
+
+#define PIXEL_RECT(name, w, h) \
+    LOCAL_ALIGNED_32(uint8_t, name##_buf, [sizeof(uint16_t) * 
(((h)+32)*(FFALIGN(w,64)+64) + 64)],); \
+    av_unused ptrdiff_t name##_stride = sizeof(uint16_t) * (FFALIGN(w,64)+64); 
\
+    av_unused int name##_buf_h = (h)+32; \
+    uint8_t *name = name##_buf + (FFALIGN(w,64)+64)*16 + 64
+
+#define CLEAR_BUF_RECT(name) \
+    memset(name##_buf, 0x99, name##_stride * name##_buf_h + 64)
+#define CLEAR_PIXEL_RECT(name) \
+    CLEAR_BUF_RECT(name)
+
 #define DECL_CHECKASM_CHECK_FUNC(type) \
 int checkasm_check_##type(const char *file, int line, \
                           const type *buf1, ptrdiff_t stride1, \
                           const type *buf2, ptrdiff_t stride2, \
-                          int w, int h, const char *name)
+                          int w, int h, const char *name, \
+                          int align_w, int align_h, \
+                          int padding)
 
 DECL_CHECKASM_CHECK_FUNC(uint8_t);
 DECL_CHECKASM_CHECK_FUNC(uint16_t);
@@ -390,18 +409,36 @@ DECL_CHECKASM_CHECK_FUNC(int32_t);
 #define PASTE(a,b) a ## b
 #define CONCAT(a,b) PASTE(a,b)
 
-#define checkasm_check(prefix, ...) CONCAT(checkasm_check_, prefix)(__FILE__, 
__LINE__, __VA_ARGS__)
+#define checkasm_check2(prefix, ...) CONCAT(checkasm_check_, prefix)(__FILE__, 
__LINE__, __VA_ARGS__)
+#define checkasm_check(prefix, ...) checkasm_check2(prefix, __VA_ARGS__, 0, 0, 
0)
+/* Check a pointer from BUF_RECT, checking whether there have been
+ * writes outside of the designated area. */
+#define checkasm_check_padded(...) \
+    checkasm_check2(__VA_ARGS__, 1, 1, 8)
+/* Check a pointer from BUF_RECT, checking whether there have been
+ * writes outside of the designated area. Allow writing slightly past the
+ * end of the buffer, by aligning w/h to align_w/align_h, and checking
+ * for overwrites outside of that. */
+#define checkasm_check_padded_align(...) \
+    checkasm_check2(__VA_ARGS__, 8)
 
 /* This assumes that there is a local variable named "bit_depth".
  * For tests that don't have that and only operate on a single
  * bitdepth, just call checkasm_check(uint8_t, ...) directly. */
-#define checkasm_check_pixel(buf1, stride1, buf2, stride2, ...) \
+#define checkasm_check_pixel2(buf1, stride1, buf2, stride2, ...) \
     ((bit_depth > 8) ?                                          \
-     checkasm_check(uint16_t, (const uint16_t*)buf1, stride1,   \
-                              (const uint16_t*)buf2, stride2,   \
-                              __VA_ARGS__) :                    \
-     checkasm_check(uint8_t,  (const uint8_t*) buf1, stride1,   \
-                              (const uint8_t*) buf2, stride2,   \
-                              __VA_ARGS__))
+     checkasm_check2(uint16_t, (const uint16_t*)buf1, stride1,   \
+                               (const uint16_t*)buf2, stride2,   \
+                               __VA_ARGS__) :                    \
+     checkasm_check2(uint8_t,  (const uint8_t*) buf1, stride1,   \
+                               (const uint8_t*) buf2, stride2,   \
+                               __VA_ARGS__))
+#define checkasm_check_pixel(...) \
+    checkasm_check_pixel2(__VA_ARGS__, 0, 0, 0)
+#define checkasm_check_pixel_padded(...) \
+    checkasm_check_pixel2(__VA_ARGS__, 1, 1, 8)
+#define checkasm_check_pixel_padded_align(...) \
+    checkasm_check_pixel2(__VA_ARGS__, 8)
+
 
 #endif /* TESTS_CHECKASM_CHECKASM_H */
-- 
2.39.5 (Apple Git-154)

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to