Blame SOURCES/0011-CVE-2019-7637-Fix-in-integer-overflow-in-SDL_Calcula.patch

cfd472
From 7cafd3e820489f17f86d0d897ad9719ef54599f1 Mon Sep 17 00:00:00 2001
cfd472
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
cfd472
Date: Mon, 18 Feb 2019 13:53:16 +0100
cfd472
Subject: [PATCH 11/11] CVE-2019-7637: Fix in integer overflow in
cfd472
 SDL_CalculatePitch
cfd472
MIME-Version: 1.0
cfd472
Content-Type: text/plain; charset=UTF-8
cfd472
Content-Transfer-Encoding: 8bit
cfd472
cfd472
If a too large width is passed to SDL_SetVideoMode() the width travels
cfd472
to SDL_CalculatePitch() where the width (e.g. 65535) is multiplied by
cfd472
BytesPerPixel (e.g. 4) and the result is stored into Uint16 pitch
cfd472
variable. During this arithmetics an integer overflow can happen (e.g.
cfd472
the value is clamped as 65532). As a result SDL_Surface with a pitch
cfd472
smaller than width * BytesPerPixel is created, too small pixel buffer
cfd472
is allocated and when the SDL_Surface is processed in SDL_FillRect()
cfd472
a buffer overflow occurs.
cfd472
cfd472
This can be reproduced with "./graywin -width 21312312313123213213213"
cfd472
command.
cfd472
cfd472
This patch fixes is by using a very careful arithmetics in
cfd472
SDL_CalculatePitch(). If an overflow is detected, an error is reported
cfd472
back as a special 0 value. We assume that 0-width surfaces do not
cfd472
occur in the wild. Since SDL_CalculatePitch() is a private function,
cfd472
we can change the semantics.
cfd472
cfd472
CVE-2019-7637
cfd472
https://bugzilla.libsdl.org/show_bug.cgi?id=4497
cfd472
cfd472
Signed-off-by: Petr Písař <ppisar@redhat.com>
cfd472
---
cfd472
 src/video/SDL_pixels.c          | 41 +++++++++++++++++++++++++++------
cfd472
 src/video/gapi/SDL_gapivideo.c  |  3 +++
cfd472
 src/video/nanox/SDL_nxvideo.c   |  4 ++++
cfd472
 src/video/ps2gs/SDL_gsvideo.c   |  3 +++
cfd472
 src/video/ps3/SDL_ps3video.c    |  3 +++
cfd472
 src/video/windib/SDL_dibvideo.c |  3 +++
cfd472
 src/video/windx5/SDL_dx5video.c |  3 +++
cfd472
 src/video/x11/SDL_x11video.c    |  4 ++++
cfd472
 8 files changed, 57 insertions(+), 7 deletions(-)
cfd472
cfd472
diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c
cfd472
index 1a7fd518f..44626b749 100644
cfd472
--- a/src/video/SDL_pixels.c
cfd472
+++ b/src/video/SDL_pixels.c
cfd472
@@ -286,26 +286,53 @@ void SDL_DitherColors(SDL_Color *colors, int bpp)
cfd472
 	}
cfd472
 }
cfd472
 /* 
cfd472
- * Calculate the pad-aligned scanline width of a surface
cfd472
+ * Calculate the pad-aligned scanline width of a surface. Return 0 in case of
cfd472
+ * an error.
cfd472
  */
cfd472
 Uint16 SDL_CalculatePitch(SDL_Surface *surface)
cfd472
 {
cfd472
-	Uint16 pitch;
cfd472
+	unsigned int pitch = 0;
cfd472
 
cfd472
 	/* Surface should be 4-byte aligned for speed */
cfd472
-	pitch = surface->w*surface->format->BytesPerPixel;
cfd472
+	/* The code tries to prevent from an Uint16 overflow. */;
cfd472
+	for (Uint8 byte = surface->format->BytesPerPixel; byte; byte--) {
cfd472
+		pitch += (unsigned int)surface->w;
cfd472
+		if (pitch < surface->w) {
cfd472
+			SDL_SetError("A scanline is too wide");
cfd472
+			return(0);
cfd472
+		}
cfd472
+	}
cfd472
 	switch (surface->format->BitsPerPixel) {
cfd472
 		case 1:
cfd472
-			pitch = (pitch+7)/8;
cfd472
+			if (pitch % 8) {
cfd472
+				pitch = pitch / 8 + 1;
cfd472
+			} else {
cfd472
+				pitch = pitch / 8;
cfd472
+			}
cfd472
 			break;
cfd472
 		case 4:
cfd472
-			pitch = (pitch+1)/2;
cfd472
+			if (pitch % 2) {
cfd472
+				pitch = pitch / 2 + 1;
cfd472
+			} else {
cfd472
+				pitch = pitch / 2;
cfd472
+			}
cfd472
 			break;
cfd472
 		default:
cfd472
 			break;
cfd472
 	}
cfd472
-	pitch = (pitch + 3) & ~3;	/* 4-byte aligning */
cfd472
-	return(pitch);
cfd472
+	/* 4-byte aligning */
cfd472
+	if (pitch & 3) {
cfd472
+		if (pitch + 3 < pitch) {
cfd472
+			SDL_SetError("A scanline is too wide");
cfd472
+			return(0);
cfd472
+		}
cfd472
+		pitch = (pitch + 3) & ~3;
cfd472
+	}
cfd472
+	if (pitch > 0xFFFF) {
cfd472
+		SDL_SetError("A scanline is too wide");
cfd472
+		return(0);
cfd472
+	}
cfd472
+	return((Uint16)pitch);
cfd472
 }
cfd472
 /*
cfd472
  * Match an RGB value to a particular palette index
cfd472
diff --git a/src/video/gapi/SDL_gapivideo.c b/src/video/gapi/SDL_gapivideo.c
cfd472
index 86deadc75..8a0648536 100644
cfd472
--- a/src/video/gapi/SDL_gapivideo.c
cfd472
+++ b/src/video/gapi/SDL_gapivideo.c
cfd472
@@ -733,6 +733,9 @@ SDL_Surface *GAPI_SetVideoMode(_THIS, SDL_Surface *current,
cfd472
 	video->w = gapi->w = width;
cfd472
 	video->h = gapi->h = height;
cfd472
 	video->pitch = SDL_CalculatePitch(video); 
cfd472
+	if (!current->pitch) {
cfd472
+		return(NULL);
cfd472
+	}
cfd472
 
cfd472
 	/* Small fix for WinCE/Win32 - when activating window
cfd472
 	   SDL_VideoSurface is equal to zero, so activating code
cfd472
diff --git a/src/video/nanox/SDL_nxvideo.c b/src/video/nanox/SDL_nxvideo.c
cfd472
index b188e0958..cbdd09a08 100644
cfd472
--- a/src/video/nanox/SDL_nxvideo.c
cfd472
+++ b/src/video/nanox/SDL_nxvideo.c
cfd472
@@ -378,6 +378,10 @@ SDL_Surface * NX_SetVideoMode (_THIS, SDL_Surface * current,
cfd472
         current -> w = width ;
cfd472
         current -> h = height ;
cfd472
         current -> pitch = SDL_CalculatePitch (current) ;
cfd472
+        if (!current->pitch) {
cfd472
+            current = NULL;
cfd472
+            goto done;
cfd472
+        }
cfd472
         NX_ResizeImage (this, current, flags) ;
cfd472
     }
cfd472
 
cfd472
diff --git a/src/video/ps2gs/SDL_gsvideo.c b/src/video/ps2gs/SDL_gsvideo.c
cfd472
index e172c60dc..329086680 100644
cfd472
--- a/src/video/ps2gs/SDL_gsvideo.c
cfd472
+++ b/src/video/ps2gs/SDL_gsvideo.c
cfd472
@@ -479,6 +479,9 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
cfd472
 	current->w = width;
cfd472
 	current->h = height;
cfd472
 	current->pitch = SDL_CalculatePitch(current);
cfd472
+	if (!current->pitch) {
cfd472
+		return(NULL);
cfd472
+	}
cfd472
 
cfd472
 	/* Memory map the DMA area for block memory transfer */
cfd472
 	if ( ! mapped_mem ) {
cfd472
diff --git a/src/video/ps3/SDL_ps3video.c b/src/video/ps3/SDL_ps3video.c
cfd472
index d5519e051..17848e33a 100644
cfd472
--- a/src/video/ps3/SDL_ps3video.c
cfd472
+++ b/src/video/ps3/SDL_ps3video.c
cfd472
@@ -339,6 +339,9 @@ static SDL_Surface *PS3_SetVideoMode(_THIS, SDL_Surface * current, int width, in
cfd472
 	current->w = width;
cfd472
 	current->h = height;
cfd472
 	current->pitch = SDL_CalculatePitch(current);
cfd472
+	if (!current->pitch) {
cfd472
+		return(NULL);
cfd472
+	}
cfd472
 
cfd472
 	/* Alloc aligned mem for current->pixels */
cfd472
 	s_pixels = memalign(16, current->h * current->pitch);
cfd472
diff --git a/src/video/windib/SDL_dibvideo.c b/src/video/windib/SDL_dibvideo.c
cfd472
index 6187bfcf7..86ebb12a3 100644
cfd472
--- a/src/video/windib/SDL_dibvideo.c
cfd472
+++ b/src/video/windib/SDL_dibvideo.c
cfd472
@@ -675,6 +675,9 @@ SDL_Surface *DIB_SetVideoMode(_THIS, SDL_Surface *current,
cfd472
 	video->w = width;
cfd472
 	video->h = height;
cfd472
 	video->pitch = SDL_CalculatePitch(video);
cfd472
+	if (!current->pitch) {
cfd472
+		return(NULL);
cfd472
+	}
cfd472
 
cfd472
 	/* Small fix for WinCE/Win32 - when activating window
cfd472
 	   SDL_VideoSurface is equal to zero, so activating code
cfd472
diff --git a/src/video/windx5/SDL_dx5video.c b/src/video/windx5/SDL_dx5video.c
cfd472
index f80ca97b0..39fc4fc37 100644
cfd472
--- a/src/video/windx5/SDL_dx5video.c
cfd472
+++ b/src/video/windx5/SDL_dx5video.c
cfd472
@@ -1127,6 +1127,9 @@ SDL_Surface *DX5_SetVideoMode(_THIS, SDL_Surface *current,
cfd472
 		video->w = width;
cfd472
 		video->h = height;
cfd472
 		video->pitch = SDL_CalculatePitch(video);
cfd472
+		if (!current->pitch) {
cfd472
+			return(NULL);
cfd472
+		}
cfd472
 
cfd472
 #ifndef NO_CHANGEDISPLAYSETTINGS
cfd472
 		/* Set fullscreen mode if appropriate.
cfd472
diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c
cfd472
index 79e60f971..45d1f79be 100644
cfd472
--- a/src/video/x11/SDL_x11video.c
cfd472
+++ b/src/video/x11/SDL_x11video.c
cfd472
@@ -1220,6 +1220,10 @@ SDL_Surface *X11_SetVideoMode(_THIS, SDL_Surface *current,
cfd472
 		current->w = width;
cfd472
 		current->h = height;
cfd472
 		current->pitch = SDL_CalculatePitch(current);
cfd472
+		if (!current->pitch) {
cfd472
+			current = NULL;
cfd472
+			goto done;
cfd472
+		}
cfd472
 		if (X11_ResizeImage(this, current, flags) < 0) {
cfd472
 			current = NULL;
cfd472
 			goto done;
cfd472
-- 
cfd472
2.21.0
cfd472