diff options
author | Henrik Gramner <gramner@twoorioles.com> | 2019-02-05 17:34:08 +0300 |
---|---|---|
committer | Henrik Gramner <henrik@gramner.com> | 2019-02-05 19:34:30 +0300 |
commit | caca57251642b5fc2a71dee3034cde300ff0c621 (patch) | |
tree | 394a70329b107e01de74907ae95b3dd5669ae5df /src/mc_tmpl.c | |
parent | ad4d1c4383b7705157807f2c364fca3ee3d713ef (diff) |
mc: Ensure high bitdepth intermediates fits in int16_t
An extreme edge case with the combination of 8-tap sharp_sharp, mx and my
both around 8, and a very specific pixel input pattern can cause overflows.
Add code to checkasm to trigger this scenario.
Diffstat (limited to 'src/mc_tmpl.c')
-rw-r--r-- | src/mc_tmpl.c | 48 |
1 files changed, 33 insertions, 15 deletions
diff --git a/src/mc_tmpl.c b/src/mc_tmpl.c index 93a6b3c..77f24dd 100644 --- a/src/mc_tmpl.c +++ b/src/mc_tmpl.c @@ -39,9 +39,14 @@ #if BITDEPTH == 8 #define get_intermediate_bits(bitdepth_max) 4 +// Output in interval [-5132, 9212], fits in int16_t as is +#define PREP_BIAS 0 #else // 4 for 10 bits/component, 2 for 12 bits/component #define get_intermediate_bits(bitdepth_max) (14 - bitdepth_from_max(bitdepth_max)) +// Output in interval [-20588, 36956] (10-bit), [-20602, 36983] (12-bit) +// Subtract a bias to ensure the output fits in int16_t +#define PREP_BIAS 8192 #endif static NOINLINE void @@ -63,7 +68,7 @@ prep_c(int16_t *tmp, const pixel *src, const ptrdiff_t src_stride, const int intermediate_bits = get_intermediate_bits(bitdepth_max); do { for (int x = 0; x < w; x++) - tmp[x] = src[x] << intermediate_bits; + tmp[x] = (src[x] << intermediate_bits) - PREP_BIAS; tmp += w; src += src_stride; @@ -237,8 +242,12 @@ prep_8tap_c(int16_t *tmp, const pixel *src, ptrdiff_t src_stride, mid_ptr = mid + 128 * 3; do { - for (int x = 0; x < w; x++) - tmp[x] = DAV1D_FILTER_8TAP_RND(mid_ptr, x, fv, 128, 6); + for (int x = 0; x < w; x++) { + int t = DAV1D_FILTER_8TAP_RND(mid_ptr, x, fv, 128, 6) - + PREP_BIAS; + assert(t >= INT16_MIN && t <= INT16_MAX); + tmp[x] = t; + } mid_ptr += 128; tmp += w; @@ -247,7 +256,8 @@ prep_8tap_c(int16_t *tmp, const pixel *src, ptrdiff_t src_stride, do { for (int x = 0; x < w; x++) tmp[x] = DAV1D_FILTER_8TAP_RND(src, x, fh, 1, - 6 - intermediate_bits); + 6 - intermediate_bits) - + PREP_BIAS; tmp += w; src += src_stride; @@ -257,7 +267,8 @@ prep_8tap_c(int16_t *tmp, const pixel *src, ptrdiff_t src_stride, do { for (int x = 0; x < w; x++) tmp[x] = DAV1D_FILTER_8TAP_RND(src, x, fv, src_stride, - 6 - intermediate_bits); + 6 - intermediate_bits) - + PREP_BIAS; tmp += w; src += src_stride; @@ -302,7 +313,8 @@ prep_8tap_scaled_c(int16_t *tmp, const pixel *src, ptrdiff_t src_stride, GET_V_FILTER(my >> 6); for (x = 0; x < w; x++) - tmp[x] = fv ? DAV1D_FILTER_8TAP_RND(mid_ptr, x, fv, 128, 6) : mid_ptr[x]; + tmp[x] = (fv ? DAV1D_FILTER_8TAP_RND(mid_ptr, x, fv, 128, 6) + : mid_ptr[x]) - PREP_BIAS; my += dy; mid_ptr += (my >> 10) * 128; @@ -499,7 +511,8 @@ static void prep_bilin_c(int16_t *tmp, mid_ptr = mid; do { for (int x = 0; x < w; x++) - tmp[x] = FILTER_BILIN_RND(mid_ptr, x, my, 128, 4); + tmp[x] = FILTER_BILIN_RND(mid_ptr, x, my, 128, 4) - + PREP_BIAS; mid_ptr += 128; tmp += w; @@ -508,7 +521,8 @@ static void prep_bilin_c(int16_t *tmp, do { for (int x = 0; x < w; x++) tmp[x] = FILTER_BILIN_RND(src, x, mx, 1, - 4 - intermediate_bits); + 4 - intermediate_bits) - + PREP_BIAS; tmp += w; src += src_stride; @@ -518,7 +532,7 @@ static void prep_bilin_c(int16_t *tmp, do { for (int x = 0; x < w; x++) tmp[x] = FILTER_BILIN_RND(src, x, my, src_stride, - 4 - intermediate_bits); + 4 - intermediate_bits) - PREP_BIAS; tmp += w; src += src_stride; @@ -557,7 +571,7 @@ static void prep_bilin_scaled_c(int16_t *tmp, int x; for (x = 0; x < w; x++) - tmp[x] = FILTER_BILIN_RND(mid_ptr, x, my >> 6, 128, 4); + tmp[x] = FILTER_BILIN_RND(mid_ptr, x, my >> 6, 128, 4) - PREP_BIAS; my += dy; mid_ptr += (my >> 10) * 128; @@ -571,7 +585,8 @@ static void avg_c(pixel *dst, const ptrdiff_t dst_stride, HIGHBD_DECL_SUFFIX) { const int intermediate_bits = get_intermediate_bits(bitdepth_max); - const int sh = intermediate_bits + 1, rnd = 1 << intermediate_bits; + const int sh = intermediate_bits + 1; + const int rnd = (1 << intermediate_bits) + PREP_BIAS * 2; do { for (int x = 0; x < w; x++) dst[x] = iclip_pixel((tmp1[x] + tmp2[x] + rnd) >> sh); @@ -587,7 +602,8 @@ static void w_avg_c(pixel *dst, const ptrdiff_t dst_stride, const int weight HIGHBD_DECL_SUFFIX) { const int intermediate_bits = get_intermediate_bits(bitdepth_max); - const int sh = intermediate_bits + 4, rnd = 8 << intermediate_bits; + const int sh = intermediate_bits + 4; + const int rnd = (8 << intermediate_bits) + PREP_BIAS * 16; do { for (int x = 0; x < w; x++) dst[x] = iclip_pixel((tmp1[x] * weight + @@ -604,7 +620,8 @@ static void mask_c(pixel *dst, const ptrdiff_t dst_stride, const uint8_t *mask HIGHBD_DECL_SUFFIX) { const int intermediate_bits = get_intermediate_bits(bitdepth_max); - const int sh = intermediate_bits + 6, rnd = 32 << intermediate_bits; + const int sh = intermediate_bits + 6; + const int rnd = (32 << intermediate_bits) + PREP_BIAS * 64; do { for (int x = 0; x < w; x++) dst[x] = iclip_pixel((tmp1[x] * mask[x] + @@ -668,7 +685,8 @@ static void w_mask_c(pixel *dst, const ptrdiff_t dst_stride, // and then load this intermediate to calculate final value for odd rows const int intermediate_bits = get_intermediate_bits(bitdepth_max); const int bitdepth = bitdepth_from_max(bitdepth_max); - const int sh = intermediate_bits + 6, rnd = 32 << intermediate_bits; + const int sh = intermediate_bits + 6; + const int rnd = (32 << intermediate_bits) + PREP_BIAS * 64; const int mask_sh = bitdepth + intermediate_bits - 4; const int mask_rnd = 1 << (mask_sh - 5); do { @@ -797,7 +815,7 @@ static void warp_affine_8x8t_c(int16_t *tmp, const ptrdiff_t tmp_stride, const int8_t *const filter = dav1d_mc_warp_filter[64 + ((tmy + 512) >> 10)]; - tmp[x] = FILTER_WARP_RND(mid_ptr, x, filter, 8, 7); + tmp[x] = FILTER_WARP_RND(mid_ptr, x, filter, 8, 7) - PREP_BIAS; } mid_ptr += 8; tmp += tmp_stride; |