When the floor LUT index (drm_fixp2int(lut_index) is the last index of the array the ceil LUT index will point to an entry beyond the array. Make sure we guard against it and use the value of the floot LUT index.
Blurb about LUT creation and how first element should be 0x0 and last one 0xffff. Hold on, is that even correct? What should the ends of a LUT be? How does UNORM work and how does it apply to LUTs? Signed-off-by: Harry Wentland <[email protected]> Cc: Ville Syrjala <[email protected]> Cc: Pekka Paalanen <[email protected]> Cc: Simon Ser <[email protected]> Cc: Harry Wentland <[email protected]> Cc: Melissa Wen <[email protected]> Cc: Jonas Ådahl <[email protected]> Cc: Sebastian Wick <[email protected]> Cc: Shashank Sharma <[email protected]> Cc: Alexander Goins <[email protected]> Cc: Joshua Ashton <[email protected]> Cc: Michel Dänzer <[email protected]> Cc: Aleix Pol <[email protected]> Cc: Xaver Hugl <[email protected]> Cc: Victoria Brekenfeld <[email protected]> Cc: Sima <[email protected]> Cc: Uma Shankar <[email protected]> Cc: Naseer Ahmed <[email protected]> Cc: Christopher Braga <[email protected]> Cc: Abhinav Kumar <[email protected]> Cc: Arthur Grillo <[email protected]> Cc: Hector Martin <[email protected]> Cc: Liviu Dudau <[email protected]> Cc: Sasha McIntosh <[email protected]> --- drivers/gpu/drm/vkms/vkms_composer.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index a0a3a6fd2926..cf1dff162920 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -123,6 +123,8 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan enum lut_channel channel) { s64 lut_index = get_lut_index(lut, channel_value); + u16 *floor_lut_value, *ceil_lut_value; + u16 floor_channel_value, ceil_channel_value; /* * This checks if `struct drm_color_lut` has any gap added by the compiler @@ -130,11 +132,15 @@ static u16 apply_lut_to_channel_value(const struct vkms_color_lut *lut, u16 chan */ static_assert(sizeof(struct drm_color_lut) == sizeof(__u16) * 4); - u16 *floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)]; - u16 *ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)]; + floor_lut_value = (__u16 *)&lut->base[drm_fixp2int(lut_index)]; + if (drm_fixp2int(lut_index) == (lut->lut_length - 1)) + /* We're at the end of the LUT array, use same value for ceil and floor */ + ceil_lut_value = floor_lut_value; + else + ceil_lut_value = (__u16 *)&lut->base[drm_fixp2int_ceil(lut_index)]; - u16 floor_channel_value = floor_lut_value[channel]; - u16 ceil_channel_value = ceil_lut_value[channel]; + floor_channel_value = floor_lut_value[channel]; + ceil_channel_value = ceil_lut_value[channel]; return lerp_u16(floor_channel_value, ceil_channel_value, lut_index & DRM_FIXED_DECIMAL_MASK); -- 2.42.0
