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 0f7f90bdd67386715e95ac53e9be28f890cc6b89..237a46522e8177120f815190199fcbaaf7c0c654 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;