Commit 54718747 authored by Anson Jacob's avatar Anson Jacob Committed by Alex Deucher
Browse files

drm/amd/display: Fix UBSAN: shift-out-of-bounds warning



[Why]
On NAVI14 CONFIG_UBSAN reported shift-out-of-bounds at
display_rq_dlg_calc_20v2.c:304:38

rq_param->misc.rq_c.blk256_height is 0 when chroma(*_c) is invalid.
dml_log2 returns -1023 for log2(0), although log2(0) is undefined.

Which ended up as:
rq_param->dlg.rq_c.swath_height = 1 << -1023

[How]
Fix applied on all dml versions.
1. Ensure dml_log2 is only called if the argument is greater than 0.
2. Subtract req128_l/req128_c from log2_swath_height_l/log2_swath_height_c
   only when it is greater than 0.

Tested-by: default avatarDaniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: default avatarAnson Jacob <Anson.Jacob@amd.com>
Reviewed-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarSolomon Chiu <solomon.chiu@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3d223c55
Loading
Loading
Loading
Loading
+23 −5
Original line number Diff line number Diff line
@@ -293,13 +293,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib,
	if (surf_linear) {
		log2_swath_height_l = 0;
		log2_swath_height_c = 0;
	} else if (!surf_vert) {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c;
	} else {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c;
		unsigned int swath_height_l;
		unsigned int swath_height_c;

		if (!surf_vert) {
			swath_height_l = rq_param->misc.rq_l.blk256_height;
			swath_height_c = rq_param->misc.rq_c.blk256_height;
		} else {
			swath_height_l = rq_param->misc.rq_l.blk256_width;
			swath_height_c = rq_param->misc.rq_c.blk256_width;
		}

		if (swath_height_l > 0)
			log2_swath_height_l = dml_log2(swath_height_l);

		if (req128_l && log2_swath_height_l > 0)
			log2_swath_height_l -= 1;

		if (swath_height_c > 0)
			log2_swath_height_c = dml_log2(swath_height_c);

		if (req128_c && log2_swath_height_c > 0)
			log2_swath_height_c -= 1;
	}

	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;

+23 −5
Original line number Diff line number Diff line
@@ -293,13 +293,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib,
	if (surf_linear) {
		log2_swath_height_l = 0;
		log2_swath_height_c = 0;
	} else if (!surf_vert) {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c;
	} else {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c;
		unsigned int swath_height_l;
		unsigned int swath_height_c;

		if (!surf_vert) {
			swath_height_l = rq_param->misc.rq_l.blk256_height;
			swath_height_c = rq_param->misc.rq_c.blk256_height;
		} else {
			swath_height_l = rq_param->misc.rq_l.blk256_width;
			swath_height_c = rq_param->misc.rq_c.blk256_width;
		}

		if (swath_height_l > 0)
			log2_swath_height_l = dml_log2(swath_height_l);

		if (req128_l && log2_swath_height_l > 0)
			log2_swath_height_l -= 1;

		if (swath_height_c > 0)
			log2_swath_height_c = dml_log2(swath_height_c);

		if (req128_c && log2_swath_height_c > 0)
			log2_swath_height_c -= 1;
	}

	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;

+23 −5
Original line number Diff line number Diff line
@@ -277,13 +277,31 @@ static void handle_det_buf_split(
	if (surf_linear) {
		log2_swath_height_l = 0;
		log2_swath_height_c = 0;
	} else if (!surf_vert) {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c;
	} else {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c;
		unsigned int swath_height_l;
		unsigned int swath_height_c;

		if (!surf_vert) {
			swath_height_l = rq_param->misc.rq_l.blk256_height;
			swath_height_c = rq_param->misc.rq_c.blk256_height;
		} else {
			swath_height_l = rq_param->misc.rq_l.blk256_width;
			swath_height_c = rq_param->misc.rq_c.blk256_width;
		}

		if (swath_height_l > 0)
			log2_swath_height_l = dml_log2(swath_height_l);

		if (req128_l && log2_swath_height_l > 0)
			log2_swath_height_l -= 1;

		if (swath_height_c > 0)
			log2_swath_height_c = dml_log2(swath_height_c);

		if (req128_c && log2_swath_height_c > 0)
			log2_swath_height_c -= 1;
	}

	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;

+23 −5
Original line number Diff line number Diff line
@@ -237,13 +237,31 @@ static void handle_det_buf_split(struct display_mode_lib *mode_lib,
	if (surf_linear) {
		log2_swath_height_l = 0;
		log2_swath_height_c = 0;
	} else if (!surf_vert) {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c;
	} else {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c;
		unsigned int swath_height_l;
		unsigned int swath_height_c;

		if (!surf_vert) {
			swath_height_l = rq_param->misc.rq_l.blk256_height;
			swath_height_c = rq_param->misc.rq_c.blk256_height;
		} else {
			swath_height_l = rq_param->misc.rq_l.blk256_width;
			swath_height_c = rq_param->misc.rq_c.blk256_width;
		}

		if (swath_height_l > 0)
			log2_swath_height_l = dml_log2(swath_height_l);

		if (req128_l && log2_swath_height_l > 0)
			log2_swath_height_l -= 1;

		if (swath_height_c > 0)
			log2_swath_height_c = dml_log2(swath_height_c);

		if (req128_c && log2_swath_height_c > 0)
			log2_swath_height_c -= 1;
	}

	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;

+23 −5
Original line number Diff line number Diff line
@@ -344,13 +344,31 @@ static void handle_det_buf_split(
	if (surf_linear) {
		log2_swath_height_l = 0;
		log2_swath_height_c = 0;
	} else if (!surf_vert) {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_height) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_height) - req128_c;
	} else {
		log2_swath_height_l = dml_log2(rq_param->misc.rq_l.blk256_width) - req128_l;
		log2_swath_height_c = dml_log2(rq_param->misc.rq_c.blk256_width) - req128_c;
		unsigned int swath_height_l;
		unsigned int swath_height_c;

		if (!surf_vert) {
			swath_height_l = rq_param->misc.rq_l.blk256_height;
			swath_height_c = rq_param->misc.rq_c.blk256_height;
		} else {
			swath_height_l = rq_param->misc.rq_l.blk256_width;
			swath_height_c = rq_param->misc.rq_c.blk256_width;
		}

		if (swath_height_l > 0)
			log2_swath_height_l = dml_log2(swath_height_l);

		if (req128_l && log2_swath_height_l > 0)
			log2_swath_height_l -= 1;

		if (swath_height_c > 0)
			log2_swath_height_c = dml_log2(swath_height_c);

		if (req128_c && log2_swath_height_c > 0)
			log2_swath_height_c -= 1;
	}

	rq_param->dlg.rq_l.swath_height = 1 << log2_swath_height_l;
	rq_param->dlg.rq_c.swath_height = 1 << log2_swath_height_c;