Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[media] sh_vou: avoid going past arrays

Smatch reports two issues:
drivers/media/platform/sh_vou.c:670 vou_adjust_output() error: buffer overflow 'vou_scale_v_num' 3 <= 4
drivers/media/platform/sh_vou.c:670 vou_adjust_output() error: buffer overflow 'vou_scale_v_den' 3 <= 4

It seems that there's actually a bug here: the same var (idx) is used
as an index for vertical and horizontal scaling arrays. However,
there are 4 elements on the h arrays, and only 3 at the v ones.

On the first loop, it may select index 4 for the horizontal array.

In this case, if the second loop fails to select an index, the
code would keep using 4 for the vertical array, with is past of
the array sizes.

The intent here seems to use index 0, if the scale is not found.

So, use a separate var for the vertical index.

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

+7 -7
+7 -7
drivers/media/platform/sh_vou.c
··· 600 600 { 601 601 unsigned int best_err = UINT_MAX, best = geo->in_width, 602 602 width_max, height_max, img_height_max; 603 - int i, idx = 0; 603 + int i, idx_h = 0, idx_v = 0; 604 604 605 605 if (std & V4L2_STD_525_60) { 606 606 width_max = 858; ··· 625 625 err = abs(found - geo->output.width); 626 626 if (err < best_err) { 627 627 best_err = err; 628 - idx = i; 628 + idx_h = i; 629 629 best = found; 630 630 } 631 631 if (!err) ··· 633 633 } 634 634 635 635 geo->output.width = best; 636 - geo->scale_idx_h = idx; 636 + geo->scale_idx_h = idx_h; 637 637 if (geo->output.left + best > width_max) 638 638 geo->output.left = width_max - best; 639 639 640 640 pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width, 641 - vou_scale_h_num[idx], vou_scale_h_den[idx], best); 641 + vou_scale_h_num[idx_h], vou_scale_h_den[idx_h], best); 642 642 643 643 best_err = UINT_MAX; 644 644 ··· 655 655 err = abs(found - geo->output.height); 656 656 if (err < best_err) { 657 657 best_err = err; 658 - idx = i; 658 + idx_v = i; 659 659 best = found; 660 660 } 661 661 if (!err) ··· 663 663 } 664 664 665 665 geo->output.height = best; 666 - geo->scale_idx_v = idx; 666 + geo->scale_idx_v = idx_v; 667 667 if (geo->output.top + best > height_max) 668 668 geo->output.top = height_max - best; 669 669 670 670 pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height, 671 - vou_scale_v_num[idx], vou_scale_v_den[idx], best); 671 + vou_scale_v_num[idx_v], vou_scale_v_den[idx_v], best); 672 672 } 673 673 674 674 static int sh_vou_s_fmt_vid_out(struct file *file, void *priv,