vpos (int) field multiplied by crtc_htotal (u16) may cause
implicit promotion of the latter and overflow the result causing
undefined behavior.

Cast the u16 operand to (s32) type to avoid that.

Signed-off-by: Krzysztof Karas <[email protected]>
---

v4:
* use s32 cast instead of int

Andi suggested using u32 type, but that breaks the test. The
values of delta_ns are visibly different when crtc_htotal is
cast to unsigned value. Here are a few before any changes:

delta_ns: 11229629
delta_ns: 11244444
delta_ns: -592592
delta_ns: -222222
delta_ns: 15985185
delta_ns: -562962
delta_ns: -548148
delta_ns: -400000
delta_ns: -592592
delta_ns: -607407
delta_ns: -592592
delta_ns: -577777

with cast to s32:

delta_ns: 5348148
delta_ns: 5362962
delta_ns: -592592
delta_ns: -162962
delta_ns: 15985185
delta_ns: -562962
delta_ns: -548148
delta_ns: -340740
delta_ns: -607407
delta_ns: -651851
delta_ns: -651851
delta_ns: -637037

with cast to u32:

delta_ns: 4607407
delta_ns: 4622222
delta_ns: -1143084231
delta_ns: -1142580527
delta_ns: 15985185
delta_ns: -1142995342
delta_ns: -1142980527
delta_ns: -1142832379
delta_ns: -1143084231
delta_ns: -1143069416
delta_ns: -1143069416
delta_ns: -1143069416

There is a jump for the negative values from 6 digits to 10.

 drivers/gpu/drm/drm_vblank.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 61e211fd3c9c..13c771d766be 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -791,7 +791,7 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal(
         * since start of scanout at first display scanline. delta_ns
         * can be negative if start of scanout hasn't happened yet.
         */
-       delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
+       delta_ns = div_s64(1000000LL * (vpos * (s32)mode->crtc_htotal + hpos),
                           mode->crtc_clock);
 
        /* Subtract time delta from raw timestamp to get final
-- 
2.34.1

Reply via email to