Fixed CVE-2019-7635 and bug 4498 - Heap-Buffer Overflow in Blit1to4 pertaining to SDL_blit_1.c
authorSam Lantinga <slouken@libsdl.org>
Sat, 16 Mar 2019 18:34:33 -0700
changeset 126447c643f1c1887
parent 12643 76caa6065d50
child 12647 fa75f0fb9e96
Fixed CVE-2019-7635 and bug 4498 - Heap-Buffer Overflow in Blit1to4 pertaining to SDL_blit_1.c

Petr Pisar

The root cause is that the POC BMP file declares 3 colors used and 4 bpp palette, but pixel at line 28 and column 1 (counted from 0) has color number 3. Then when the image loaded into a surface is passed to SDL_DisplayFormat(), in order to convert it to a video format, a used bliting function looks up a color number 3 in a 3-element long color bliting map. (The map obviously has the same number entries as the surface format has colors.)

Proper fix should refuse broken BMP images that have a pixel with a color index higher than declared number of "used" colors. Possibly more advanced fix could try to relocate the out-of-range color index into a vacant index (if such exists).
src/video/SDL_bmp.c
     1.1 --- a/src/video/SDL_bmp.c	Sat Mar 16 18:12:26 2019 -0700
     1.2 +++ b/src/video/SDL_bmp.c	Sat Mar 16 18:34:33 2019 -0700
     1.3 @@ -246,6 +246,14 @@
     1.4          ExpandBMP = biBitCount;
     1.5          biBitCount = 8;
     1.6          break;
     1.7 +    case 2:
     1.8 +    case 3:
     1.9 +    case 5:
    1.10 +    case 6:
    1.11 +    case 7:
    1.12 +		SDL_SetError("%d-bpp BMP images are not supported", biBitCount);
    1.13 +        was_error = SDL_TRUE;
    1.14 +        goto done;
    1.15      default:
    1.16          ExpandBMP = 0;
    1.17          break;
    1.18 @@ -398,19 +406,32 @@
    1.19                              goto done;
    1.20                          }
    1.21                      }
    1.22 -                    *(bits + i) = (pixel >> shift);
    1.23 +                    bits[i] = (pixel >> shift);
    1.24 +					if (bits[i] >= biClrUsed) {
    1.25 +						SDL_SetError("A BMP image contains a pixel with a color out of the palette");
    1.26 +						was_error = SDL_TRUE;
    1.27 +						goto done;
    1.28 +					}
    1.29                      pixel <<= ExpandBMP;
    1.30                  }
    1.31              }
    1.32              break;
    1.33  
    1.34          default:
    1.35 -            if (SDL_RWread(src, bits, 1, surface->pitch)
    1.36 -                != surface->pitch) {
    1.37 +            if (SDL_RWread(src, bits, 1, surface->pitch) != surface->pitch) {
    1.38                  SDL_Error(SDL_EFREAD);
    1.39                  was_error = SDL_TRUE;
    1.40                  goto done;
    1.41              }
    1.42 +			if (biBitCount == 8 && palette && biClrUsed < (1 << biBitCount)) {
    1.43 +				for (i = 0; i < surface->w; ++i) {
    1.44 +					if (bits[i] >= biClrUsed) {
    1.45 +						SDL_SetError("A BMP image contains a pixel with a color out of the palette");
    1.46 +						was_error = SDL_TRUE;
    1.47 +						goto done;
    1.48 +					}
    1.49 +				}
    1.50 +			}
    1.51  #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    1.52              /* Byte-swap the pixels if needed. Note that the 24bpp
    1.53                 case has already been taken care of above. */