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
