amlogic/media: lcd: Fix division by zero 64/251864/1
authorSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 20 Jan 2021 05:25:45 +0000 (14:25 +0900)
committerSeung-Woo Kim <sw0312.kim@samsung.com>
Wed, 20 Jan 2021 05:28:26 +0000 (14:28 +0900)
If no lcd is set by bootargs, it can not choose lcd type from
device tree and it causes division by zero. Fix the it by checking
division value.

This fixes below ubsan warnings:
   UBSAN: Undefined behaviour in drivers/amlogic/media/vout/lcd/lcd_common.c:777:59
   UBSAN: Undefined behaviour in drivers/amlogic/media/vout/lcd/lcd_common.c:778:43
   UBSAN: Undefined behaviour in drivers/amlogic/media/vout/lcd/lcd_common.c:784:53
   UBSAN: Undefined behaviour in drivers/amlogic/media/vout/lcd/lcd_common.c:786:59
   UBSAN: Undefined behaviour in drivers/amlogic/media/vout/lcd/lcd_common.c:787:43
   division by zero
   ...
   [ffffff9200003610+  96][<ffffff9009b70fac>] __ubsan_handle_divrem_overflow+0x8c/0xc8
   [ffffff9200003670+ 144][<ffffff900a582eac>] lcd_timing_init_config+0x254/0x390
   [ffffff9200003700+ 544][<ffffff900a5aeb50>] lcd_tablet_probe+0xfa0/0x3f50
   [ffffff9200003920+  64][<ffffff900a57a51c>] lcd_mode_probe+0x54/0x6c0
   [ffffff9200003960+ 272][<ffffff900a57bf5c>] lcd_probe+0x984/0x1070
   ...

Change-Id: I6ad73fcd554715c1d7ac3cadf82ead251b596e1c
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
drivers/amlogic/media/vout/lcd/lcd_common.c

index 0f7f90b..237a465 100644 (file)
@@ -774,17 +774,28 @@ void lcd_timing_init_config(struct lcd_config_s *pconf)
        pconf->lcd_timing.de_vs_addr = de_vstart;
        pconf->lcd_timing.de_ve_addr = de_vstart + v_active - 1;
 
-       hstart = (de_hstart + h_period - hsync_bp - hsync_width) % h_period;
-       hend = (de_hstart + h_period - hsync_bp) % h_period;
+       if (h_period) {
+               hstart = (de_hstart + h_period - hsync_bp - hsync_width) % h_period;
+               hend = (de_hstart + h_period - hsync_bp) % h_period;
+       } else {
+               hstart = 0;
+               hend = 0;
+       }
        pconf->lcd_timing.hs_hs_addr = hstart;
        pconf->lcd_timing.hs_he_addr = hend;
        pconf->lcd_timing.hs_vs_addr = 0;
        pconf->lcd_timing.hs_ve_addr = v_period - 1;
 
-       pconf->lcd_timing.vs_hs_addr = (hstart + h_period) % h_period;
+       if (h_period) {
+               pconf->lcd_timing.vs_hs_addr = (hstart + h_period) % h_period;
+               vstart = (de_vstart + v_period - vsync_bp - vsync_width) % v_period;
+               vend = (de_vstart + v_period - vsync_bp) % v_period;
+       } else {
+               pconf->lcd_timing.vs_hs_addr = 0;
+               vstart = 0;
+               vend = 0;
+       }
        pconf->lcd_timing.vs_he_addr = pconf->lcd_timing.vs_hs_addr;
-       vstart = (de_vstart + v_period - vsync_bp - vsync_width) % v_period;
-       vend = (de_vstart + v_period - vsync_bp) % v_period;
        pconf->lcd_timing.vs_vs_addr = vstart;
        pconf->lcd_timing.vs_ve_addr = vend;