⬢ DragonFlyBSD Kernel Audit
DF-4696 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/sys/dev/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
index f67ae9a..a4cdf8f 100644
--- a/sys/dev/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
+++ b/sys/dev/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
@@ -418,6 +418,24 @@ void dpp1_dscl_calc_lb_num_partitions(
 	int memory_line_size_a = (line_size + 5) / 6; /* +5 to ceil */
 	int lb_memory_size, lb_memory_size_c, lb_memory_size_a, num_partitions_a;
 
+	/* Degenerate geometry guard (DF-4696): a UABI-legal plane positioned
+	 * flush off the stream window clamps recout.width to exactly 0 in
+	 * calculate_recout (dc_resource.c:639-643) while viewport.width stays
+	 * >= 16 in source pixels, so the >=16 guard in
+	 * resource_build_scaling_params (dc_resource.c:1125-1127) passes and
+	 * this function would divide by zero below. The same zero divisors
+	 * also occur when lb_bpc is -1 (unsupported depth). Report zero
+	 * partitions instead: every dpp1_dscl_is_lb_conf_valid() check then
+	 * fails and the caller falls through to the default config (warned
+	 * by the existing ASSERT) instead of faulting with #DE.
+	 */
+	if (memory_line_size_y <= 0 || memory_line_size_c <= 0 ||
+			memory_line_size_a <= 0) {
+		*num_part_y = 0;
+		*num_part_c = 0;
+		return;
+	}
+
 	if (lb_config == LB_MEMORY_CONFIG_1) {
 		lb_memory_size = 816;
 		lb_memory_size_c = 816;