mmc: msm_sdcc: fix buffer overflow conditions

This function fixes few possible buffer overflow
conditions in find_most_appropriate_phase()
function.

Change-Id: Icc17469a3850aa8531a6ef176bacc83fa2c50159
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 69ec647..f03aeac 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3201,14 +3201,15 @@
 static int find_most_appropriate_phase(struct msmsdcc_host *host,
 				u8 *phase_table, u8 total_phases)
 {
+	#define MAX_PHASES 16
 	int ret;
-	u8 ranges[16][16] = { {0}, {0} };
-	u8 phases_per_row[16] = {0};
+	u8 ranges[MAX_PHASES][MAX_PHASES] = { {0}, {0} };
+	u8 phases_per_row[MAX_PHASES] = {0};
 	int row_index = 0, col_index = 0, selected_row_index = 0, curr_max = 0;
 	int i, cnt, phase_0_raw_index = 0, phase_15_raw_index = 0;
 	bool phase_0_found = false, phase_15_found = false;
 
-	if (total_phases > 16) {
+	if (!total_phases || (total_phases > MAX_PHASES)) {
 		pr_err("%s: %s: invalid argument: total_phases=%d\n",
 			mmc_hostname(host->mmc), __func__, total_phases);
 		return -EINVAL;
@@ -3228,6 +3229,9 @@
 		}
 	}
 
+	if (row_index >= MAX_PHASES)
+		return -EINVAL;
+
 	/* Check if phase-0 is present in first valid window? */
 	if (!ranges[0][0]) {
 		phase_0_found = true;
@@ -3235,7 +3239,7 @@
 		/* Check if cycle exist between 2 valid windows */
 		for (cnt = 1; cnt <= row_index; cnt++) {
 			if (phases_per_row[cnt]) {
-				for (i = 0; i <= phases_per_row[cnt]; i++) {
+				for (i = 0; i < phases_per_row[cnt]; i++) {
 					if (ranges[cnt][i] == 15) {
 						phase_15_found = true;
 						phase_15_raw_index = cnt;
@@ -3253,12 +3257,23 @@
 		/* number of phases in raw where phase 15 is present */
 		u8 phases_15 = phases_per_row[phase_15_raw_index];
 
-		cnt = 0;
-		for (i = phases_15; i < (phases_15 + phases_0); i++) {
+		if (phases_0 + phases_15 >= MAX_PHASES)
+			/*
+			 * If there are more than 1 phase windows then total
+			 * number of phases in both the windows should not be
+			 * more than or equal to MAX_PHASES.
+			 */
+			return -EINVAL;
+
+		/* Merge 2 cyclic windows */
+		i = phases_15;
+		for (cnt = 0; cnt < phases_0; cnt++) {
 			ranges[phase_15_raw_index][i] =
 				ranges[phase_0_raw_index][cnt];
-			cnt++;
+			if (++i >= MAX_PHASES)
+				break;
 		}
+
 		phases_per_row[phase_0_raw_index] = 0;
 		phases_per_row[phase_15_raw_index] = phases_15 + phases_0;
 	}
@@ -3270,9 +3285,18 @@
 		}
 	}
 
-	i = ((curr_max * 3) / 4) - 1;
+	i = ((curr_max * 3) / 4);
+	if (i)
+		i--;
+
 	ret = (int)ranges[selected_row_index][i];
 
+	if (ret >= MAX_PHASES) {
+		ret = -EINVAL;
+		pr_err("%s: %s: invalid phase selected=%d\n",
+			mmc_hostname(host->mmc), __func__, ret);
+	}
+
 	return ret;
 }