1*4882a593Smuzhiyun# HG changeset patch 2*4882a593Smuzhiyun# User Petr Písař <ppisar@redhat.com> 3*4882a593Smuzhiyun# Date 1552788984 25200 4*4882a593Smuzhiyun# Sat Mar 16 19:16:24 2019 -0700 5*4882a593Smuzhiyun# Branch SDL-1.2 6*4882a593Smuzhiyun# Node ID 9b0e5c555c0f5ce6d2c3c19da6cc2c7fb5048bf2 7*4882a593Smuzhiyun# Parent 4646533663ae1d80c2cc6b2d6dbfb37c62491c1e 8*4882a593SmuzhiyunCVE-2019-7637: Fix in integer overflow in SDL_CalculatePitch 9*4882a593SmuzhiyunIf a too large width is passed to SDL_SetVideoMode() the width travels 10*4882a593Smuzhiyunto SDL_CalculatePitch() where the width (e.g. 65535) is multiplied by 11*4882a593SmuzhiyunBytesPerPixel (e.g. 4) and the result is stored into Uint16 pitch 12*4882a593Smuzhiyunvariable. During this arithmetics an integer overflow can happen (e.g. 13*4882a593Smuzhiyunthe value is clamped as 65532). As a result SDL_Surface with a pitch 14*4882a593Smuzhiyunsmaller than width * BytesPerPixel is created, too small pixel buffer 15*4882a593Smuzhiyunis allocated and when the SDL_Surface is processed in SDL_FillRect() 16*4882a593Smuzhiyuna buffer overflow occurs. 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunThis can be reproduced with "./graywin -width 21312312313123213213213" 19*4882a593Smuzhiyuncommand. 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunThis patch fixes is by using a very careful arithmetics in 22*4882a593SmuzhiyunSDL_CalculatePitch(). If an overflow is detected, an error is reported 23*4882a593Smuzhiyunback as a special 0 value. We assume that 0-width surfaces do not 24*4882a593Smuzhiyunoccur in the wild. Since SDL_CalculatePitch() is a private function, 25*4882a593Smuzhiyunwe can change the semantics. 26*4882a593Smuzhiyun 27*4882a593SmuzhiyunCVE-2019-7637 28*4882a593Smuzhiyunhttps://bugzilla.libsdl.org/show_bug.cgi?id=4497 29*4882a593Smuzhiyun 30*4882a593SmuzhiyunSigned-off-by: Petr Písař <ppisar@redhat.com> 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunCVE: CVE-2019-7637 33*4882a593SmuzhiyunUpstream-Status: Backport 34*4882a593SmuzhiyunSigned-off-by: Anuj Mittal <anuj.mittal@intel.com> 35*4882a593Smuzhiyun 36*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/SDL_pixels.c 37*4882a593Smuzhiyun--- a/src/video/SDL_pixels.c Sat Mar 16 18:35:33 2019 -0700 38*4882a593Smuzhiyun+++ b/src/video/SDL_pixels.c Sat Mar 16 19:16:24 2019 -0700 39*4882a593Smuzhiyun@@ -286,26 +286,53 @@ 40*4882a593Smuzhiyun } 41*4882a593Smuzhiyun } 42*4882a593Smuzhiyun /* 43*4882a593Smuzhiyun- * Calculate the pad-aligned scanline width of a surface 44*4882a593Smuzhiyun+ * Calculate the pad-aligned scanline width of a surface. Return 0 in case of 45*4882a593Smuzhiyun+ * an error. 46*4882a593Smuzhiyun */ 47*4882a593Smuzhiyun Uint16 SDL_CalculatePitch(SDL_Surface *surface) 48*4882a593Smuzhiyun { 49*4882a593Smuzhiyun- Uint16 pitch; 50*4882a593Smuzhiyun+ unsigned int pitch = 0; 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* Surface should be 4-byte aligned for speed */ 53*4882a593Smuzhiyun- pitch = surface->w*surface->format->BytesPerPixel; 54*4882a593Smuzhiyun+ /* The code tries to prevent from an Uint16 overflow. */; 55*4882a593Smuzhiyun+ for (Uint8 byte = surface->format->BytesPerPixel; byte; byte--) { 56*4882a593Smuzhiyun+ pitch += (unsigned int)surface->w; 57*4882a593Smuzhiyun+ if (pitch < surface->w) { 58*4882a593Smuzhiyun+ SDL_SetError("A scanline is too wide"); 59*4882a593Smuzhiyun+ return(0); 60*4882a593Smuzhiyun+ } 61*4882a593Smuzhiyun+ } 62*4882a593Smuzhiyun switch (surface->format->BitsPerPixel) { 63*4882a593Smuzhiyun case 1: 64*4882a593Smuzhiyun- pitch = (pitch+7)/8; 65*4882a593Smuzhiyun+ if (pitch % 8) { 66*4882a593Smuzhiyun+ pitch = pitch / 8 + 1; 67*4882a593Smuzhiyun+ } else { 68*4882a593Smuzhiyun+ pitch = pitch / 8; 69*4882a593Smuzhiyun+ } 70*4882a593Smuzhiyun break; 71*4882a593Smuzhiyun case 4: 72*4882a593Smuzhiyun- pitch = (pitch+1)/2; 73*4882a593Smuzhiyun+ if (pitch % 2) { 74*4882a593Smuzhiyun+ pitch = pitch / 2 + 1; 75*4882a593Smuzhiyun+ } else { 76*4882a593Smuzhiyun+ pitch = pitch / 2; 77*4882a593Smuzhiyun+ } 78*4882a593Smuzhiyun break; 79*4882a593Smuzhiyun default: 80*4882a593Smuzhiyun break; 81*4882a593Smuzhiyun } 82*4882a593Smuzhiyun- pitch = (pitch + 3) & ~3; /* 4-byte aligning */ 83*4882a593Smuzhiyun- return(pitch); 84*4882a593Smuzhiyun+ /* 4-byte aligning */ 85*4882a593Smuzhiyun+ if (pitch & 3) { 86*4882a593Smuzhiyun+ if (pitch + 3 < pitch) { 87*4882a593Smuzhiyun+ SDL_SetError("A scanline is too wide"); 88*4882a593Smuzhiyun+ return(0); 89*4882a593Smuzhiyun+ } 90*4882a593Smuzhiyun+ pitch = (pitch + 3) & ~3; 91*4882a593Smuzhiyun+ } 92*4882a593Smuzhiyun+ if (pitch > 0xFFFF) { 93*4882a593Smuzhiyun+ SDL_SetError("A scanline is too wide"); 94*4882a593Smuzhiyun+ return(0); 95*4882a593Smuzhiyun+ } 96*4882a593Smuzhiyun+ return((Uint16)pitch); 97*4882a593Smuzhiyun } 98*4882a593Smuzhiyun /* 99*4882a593Smuzhiyun * Match an RGB value to a particular palette index 100*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/gapi/SDL_gapivideo.c 101*4882a593Smuzhiyun--- a/src/video/gapi/SDL_gapivideo.c Sat Mar 16 18:35:33 2019 -0700 102*4882a593Smuzhiyun+++ b/src/video/gapi/SDL_gapivideo.c Sat Mar 16 19:16:24 2019 -0700 103*4882a593Smuzhiyun@@ -733,6 +733,9 @@ 104*4882a593Smuzhiyun video->w = gapi->w = width; 105*4882a593Smuzhiyun video->h = gapi->h = height; 106*4882a593Smuzhiyun video->pitch = SDL_CalculatePitch(video); 107*4882a593Smuzhiyun+ if (!current->pitch) { 108*4882a593Smuzhiyun+ return(NULL); 109*4882a593Smuzhiyun+ } 110*4882a593Smuzhiyun 111*4882a593Smuzhiyun /* Small fix for WinCE/Win32 - when activating window 112*4882a593Smuzhiyun SDL_VideoSurface is equal to zero, so activating code 113*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/nanox/SDL_nxvideo.c 114*4882a593Smuzhiyun--- a/src/video/nanox/SDL_nxvideo.c Sat Mar 16 18:35:33 2019 -0700 115*4882a593Smuzhiyun+++ b/src/video/nanox/SDL_nxvideo.c Sat Mar 16 19:16:24 2019 -0700 116*4882a593Smuzhiyun@@ -378,6 +378,10 @@ 117*4882a593Smuzhiyun current -> w = width ; 118*4882a593Smuzhiyun current -> h = height ; 119*4882a593Smuzhiyun current -> pitch = SDL_CalculatePitch (current) ; 120*4882a593Smuzhiyun+ if (!current->pitch) { 121*4882a593Smuzhiyun+ current = NULL; 122*4882a593Smuzhiyun+ goto done; 123*4882a593Smuzhiyun+ } 124*4882a593Smuzhiyun NX_ResizeImage (this, current, flags) ; 125*4882a593Smuzhiyun } 126*4882a593Smuzhiyun 127*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/ps2gs/SDL_gsvideo.c 128*4882a593Smuzhiyun--- a/src/video/ps2gs/SDL_gsvideo.c Sat Mar 16 18:35:33 2019 -0700 129*4882a593Smuzhiyun+++ b/src/video/ps2gs/SDL_gsvideo.c Sat Mar 16 19:16:24 2019 -0700 130*4882a593Smuzhiyun@@ -479,6 +479,9 @@ 131*4882a593Smuzhiyun current->w = width; 132*4882a593Smuzhiyun current->h = height; 133*4882a593Smuzhiyun current->pitch = SDL_CalculatePitch(current); 134*4882a593Smuzhiyun+ if (!current->pitch) { 135*4882a593Smuzhiyun+ return(NULL); 136*4882a593Smuzhiyun+ } 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun /* Memory map the DMA area for block memory transfer */ 139*4882a593Smuzhiyun if ( ! mapped_mem ) { 140*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/ps3/SDL_ps3video.c 141*4882a593Smuzhiyun--- a/src/video/ps3/SDL_ps3video.c Sat Mar 16 18:35:33 2019 -0700 142*4882a593Smuzhiyun+++ b/src/video/ps3/SDL_ps3video.c Sat Mar 16 19:16:24 2019 -0700 143*4882a593Smuzhiyun@@ -339,6 +339,9 @@ 144*4882a593Smuzhiyun current->w = width; 145*4882a593Smuzhiyun current->h = height; 146*4882a593Smuzhiyun current->pitch = SDL_CalculatePitch(current); 147*4882a593Smuzhiyun+ if (!current->pitch) { 148*4882a593Smuzhiyun+ return(NULL); 149*4882a593Smuzhiyun+ } 150*4882a593Smuzhiyun 151*4882a593Smuzhiyun /* Alloc aligned mem for current->pixels */ 152*4882a593Smuzhiyun s_pixels = memalign(16, current->h * current->pitch); 153*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/windib/SDL_dibvideo.c 154*4882a593Smuzhiyun--- a/src/video/windib/SDL_dibvideo.c Sat Mar 16 18:35:33 2019 -0700 155*4882a593Smuzhiyun+++ b/src/video/windib/SDL_dibvideo.c Sat Mar 16 19:16:24 2019 -0700 156*4882a593Smuzhiyun@@ -675,6 +675,9 @@ 157*4882a593Smuzhiyun video->w = width; 158*4882a593Smuzhiyun video->h = height; 159*4882a593Smuzhiyun video->pitch = SDL_CalculatePitch(video); 160*4882a593Smuzhiyun+ if (!current->pitch) { 161*4882a593Smuzhiyun+ return(NULL); 162*4882a593Smuzhiyun+ } 163*4882a593Smuzhiyun 164*4882a593Smuzhiyun /* Small fix for WinCE/Win32 - when activating window 165*4882a593Smuzhiyun SDL_VideoSurface is equal to zero, so activating code 166*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/windx5/SDL_dx5video.c 167*4882a593Smuzhiyun--- a/src/video/windx5/SDL_dx5video.c Sat Mar 16 18:35:33 2019 -0700 168*4882a593Smuzhiyun+++ b/src/video/windx5/SDL_dx5video.c Sat Mar 16 19:16:24 2019 -0700 169*4882a593Smuzhiyun@@ -1127,6 +1127,9 @@ 170*4882a593Smuzhiyun video->w = width; 171*4882a593Smuzhiyun video->h = height; 172*4882a593Smuzhiyun video->pitch = SDL_CalculatePitch(video); 173*4882a593Smuzhiyun+ if (!current->pitch) { 174*4882a593Smuzhiyun+ return(NULL); 175*4882a593Smuzhiyun+ } 176*4882a593Smuzhiyun 177*4882a593Smuzhiyun #ifndef NO_CHANGEDISPLAYSETTINGS 178*4882a593Smuzhiyun /* Set fullscreen mode if appropriate. 179*4882a593Smuzhiyundiff -r 4646533663ae -r 9b0e5c555c0f src/video/x11/SDL_x11video.c 180*4882a593Smuzhiyun--- a/src/video/x11/SDL_x11video.c Sat Mar 16 18:35:33 2019 -0700 181*4882a593Smuzhiyun+++ b/src/video/x11/SDL_x11video.c Sat Mar 16 19:16:24 2019 -0700 182*4882a593Smuzhiyun@@ -1225,6 +1225,10 @@ 183*4882a593Smuzhiyun current->w = width; 184*4882a593Smuzhiyun current->h = height; 185*4882a593Smuzhiyun current->pitch = SDL_CalculatePitch(current); 186*4882a593Smuzhiyun+ if (!current->pitch) { 187*4882a593Smuzhiyun+ current = NULL; 188*4882a593Smuzhiyun+ goto done; 189*4882a593Smuzhiyun+ } 190*4882a593Smuzhiyun if (X11_ResizeImage(this, current, flags) < 0) { 191*4882a593Smuzhiyun current = NULL; 192*4882a593Smuzhiyun goto done; 193