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

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