# HG changeset patch # User Rich Burridge # Date 1479763452 28800 # Node ID a206d468357af2e5385b9eb8fb2b42cb02c3dadd # Parent 13871af9f7460533767e73b18114d85d4c408536 25052020 problem in PYTHON-MOD/PIL 25052021 problem in PYTHON-MOD/PIL diff -r 13871af9f746 -r a206d468357a components/python/imaging/patches/06-CVE-2016-9189.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/python/imaging/patches/06-CVE-2016-9189.patch Mon Nov 21 13:24:12 2016 -0800 @@ -0,0 +1,317 @@ +For CVE-2016-9189 +https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9189 + +Python Imaging allows context-dependent attackers to obtain sensitive +information by using the "crafted image file" approach, related to an +"Integer Overflow" issue affecting the Image.core.map_buffer in map.c +component. + +Code changes based on those found upstream for Pillow at: + +https://github.com/python-pillow/Pillow/pull/2146/commits/c50ebe6459a131a1ea8ca531f10da616d3ceaa0f +for: + map.c + +https://github.com/python-pillow/Pillow/pull/2146/commits/445451c0b9347b50e0f603db33f196e207de470d +for: + PIL/Image.py + +https://github.com/python-pillow/Pillow/pull/2146/commits/1a43da7a8bda884a597f3a1623364f4719d21c14 +for: + PIL/EpsImagePlugin.py + PIL/IptcImagePlugin.py + PIL/JPegImagePlugin.py + PIL/PpmImagePlugin.py + _imaging.c + libImaging/File.c + +--- Imaging-1.1.7/map.c.orig 2016-11-21 07:50:42.925380355 +0000 ++++ Imaging-1.1.7/map.c 2016-11-21 07:53:34.182039527 +0000 +@@ -339,8 +339,18 @@ + stride = xsize * 4; + } + ++ if (ysize > INT_MAX / stride) { ++ PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize"); ++ return NULL; ++ } ++ + size = ysize * stride; + ++ if (offset > SIZE_MAX - size) { ++ PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset"); ++ return NULL; ++ } ++ + /* check buffer size */ + bytes = PyImaging_ReadBuffer(target, (const void**) &ptr); + if (bytes < 0) { +--- Imaging-1.1.7/PIL/Image.py.orig 2016-11-21 07:58:09.978008218 +0000 ++++ Imaging-1.1.7/PIL/Image.py 2016-11-21 08:02:12.063288055 +0000 +@@ -1740,6 +1740,25 @@ + + return Image()._new(core.wedge("L")) + ++ ++def _check_size(size): ++ """ ++ Common check to enforce type and sanity check on size tuples ++ ++ :param size: Should be a 2 tuple of (width, height) ++ :returns: True, or raises a ValueError ++ """ ++ ++ if not isinstance(size, tuple): ++ raise ValueError("Size must be a tuple") ++ if len(size) != 2: ++ raise ValueError("Size must be a tuple of length 2") ++ if size[0] <= 0 or size[1] <= 0: ++ raise ValueError("Width and Height must be > 0") ++ ++ return True ++ ++ + ## + # Creates a new image with the given mode and size. + # +@@ -1756,6 +1775,8 @@ + def new(mode, size, color=0): + "Create a new image" + ++ _check_size(size) ++ + if color is None: + # don't initialize + return Image()._new(core.new(mode, size)) +@@ -1792,6 +1813,8 @@ + def fromstring(mode, size, data, decoder_name="raw", *args): + "Load image from string" + ++ _check_size(size) ++ + # may pass tuple instead of argument list + if len(args) == 1 and isTupleType(args[0]): + args = args[0] +@@ -1839,6 +1862,8 @@ + def frombuffer(mode, size, data, decoder_name="raw", *args): + "Load image from string or buffer" + ++ _check_size(size) ++ + # may pass tuple instead of argument list + if len(args) == 1 and isTupleType(args[0]): + args = args[0] +--- Imaging-1.1.7/PIL/EpsImagePlugin.py.orig 2016-11-21 08:07:25.697709727 +0000 ++++ Imaging-1.1.7/PIL/EpsImagePlugin.py 2016-11-21 08:12:17.177879463 +0000 +@@ -74,12 +74,13 @@ + status = gs.close() + if status: + raise IOError("gs failed (status %d)" % status) +- im = Image.core.open_ppm(file) ++ im = Image.open(outfile) ++ im.load() + finally: + try: os.unlink(file) + except: pass + +- return im ++ return im.im.copy() + + + class PSFile: +--- Imaging-1.1.7/PIL/IptcImagePlugin.py.orig 2016-11-21 08:07:25.704128117 +0000 ++++ Imaging-1.1.7/PIL/IptcImagePlugin.py 2016-11-21 08:14:00.062399442 +0000 +@@ -192,14 +192,9 @@ + o.close() + + try: +- try: +- # fast +- self.im = Image.core.open_ppm(outfile) +- except: +- # slightly slower +- im = Image.open(outfile) +- im.load() +- self.im = im.im ++ _im = Image.open(outfile) ++ _im.load() ++ self.im = _im.im + finally: + try: os.unlink(outfile) + except: pass +--- Imaging-1.1.7/PIL/JpegImagePlugin.py.orig 2016-11-21 08:16:20.362838015 +0000 ++++ Imaging-1.1.7/PIL/JpegImagePlugin.py 2016-11-21 08:19:06.852441772 +0000 +@@ -352,7 +352,9 @@ + raise ValueError("Invalid Filename") + + try: +- self.im = Image.core.open_ppm(path) ++ _im = Image.open(path) ++ _im.load() ++ self.im = _im.im + finally: + try: os.unlink(path) + except: pass +--- Imaging-1.1.7/PIL/PpmImagePlugin.py.orig 2016-11-21 08:07:25.708512595 +0000 ++++ Imaging-1.1.7/PIL/PpmImagePlugin.py 2016-11-21 08:19:55.525463844 +0000 +@@ -93,11 +93,6 @@ + self.fp.tell(), + (rawmode, 0, 1))] + +- # ALTERNATIVE: load via builtin debug function +- # self.im = Image.core.open_ppm(self.filename) +- # self.mode = self.im.mode +- # self.size = self.im.size +- + # + # -------------------------------------------------------------------- + +--- Imaging-1.1.7/_imaging.c.orig 2016-11-21 08:07:25.710428542 +0000 ++++ Imaging-1.1.7/_imaging.c 2016-11-21 08:21:03.690730505 +0000 +@@ -684,17 +684,6 @@ + } + + static PyObject* +-_open_ppm(PyObject* self, PyObject* args) +-{ +- char* filename; +- +- if (!PyArg_ParseTuple(args, "s", &filename)) +- return NULL; +- +- return PyImagingNew(ImagingOpenPPM(filename)); +-} +- +-static PyObject* + _blend(ImagingObject* self, PyObject* args) + { + ImagingObject* imagep1; +@@ -3215,9 +3204,6 @@ + {"crc32", (PyCFunction)_crc32, 1}, + {"getcodecstatus", (PyCFunction)_getcodecstatus, 1}, + +- /* Debugging stuff */ +- {"open_ppm", (PyCFunction)_open_ppm, 1}, +- + /* Special effects (experimental) */ + #ifdef WITH_EFFECTS + {"effect_mandelbrot", (PyCFunction)_effect_mandelbrot, 1}, +--- Imaging-1.1.7/libImaging/File.c.orig 2016-11-21 08:07:25.712276651 +0000 ++++ Imaging-1.1.7/libImaging/File.c 2016-11-21 08:22:37.837774950 +0000 +@@ -20,116 +20,6 @@ + + #include + +-Imaging +-ImagingOpenPPM(const char* infile) +-{ +- FILE* fp; +- int i, c, v; +- char* mode; +- int x, y, max; +- Imaging im; +- +- if (!infile) +- return ImagingError_ValueError(NULL); +- +- fp = fopen(infile, "rb"); +- if (!fp) +- return ImagingError_IOError(); +- +- /* PPM magic */ +- if (fgetc(fp) != 'P') +- goto error; +- switch (fgetc(fp)) { +- case '4': /* FIXME: 1-bit images are not yet supported */ +- goto error; +- case '5': +- mode = "L"; +- break; +- case '6': +- mode = "RGB"; +- break; +- default: +- goto error; +- } +- +- i = 0; +- c = fgetc(fp); +- +- x = y = max = 0; +- +- while (i < 3) { +- +- /* Ignore optional comment fields */ +- while (c == '\n') { +- c = fgetc(fp); +- if (c == '#') { +- do { +- c = fgetc(fp); +- if (c == EOF) +- goto error; +- } while (c != '\n'); +- c = fgetc(fp); +- } +- } +- +- /* Skip forward to next value */ +- while (isspace(c)) +- c = fgetc(fp); +- +- /* And parse it */ +- v = 0; +- while (isdigit(c)) { +- v = v * 10 + (c - '0'); +- c = fgetc(fp); +- } +- +- if (c == EOF) +- goto error; +- +- switch (i++) { +- case 0: +- x = v; +- break; +- case 1: +- y = v; +- break; +- case 2: +- max = v; +- break; +- } +- } +- +- im = ImagingNew(mode, x, y); +- if (!im) +- return NULL; +- +- /* if (max != 255) ... FIXME: does anyone ever use this feature? */ +- +- if (strcmp(im->mode, "L") == 0) { +- +- /* PPM "L" */ +- for (y = 0; y < im->ysize; y++) +- if (fread(im->image[y], im->xsize, 1, fp) != 1) +- goto error; +- +- } else { +- +- /* PPM "RGB" or PyPPM mode */ +- for (y = 0; y < im->ysize; y++) +- for (x = i = 0; x < im->xsize; x++, i += im->pixelsize) +- if (fread(im->image[y]+i, im->bands, 1, fp) != 1) +- goto error; +- } +- +- fclose(fp); +- +- return im; +- +-error: +- fclose(fp); +- return ImagingError_IOError(); +-} +- + + int + ImagingSaveRaw(Imaging im, FILE* fp) diff -r 13871af9f746 -r a206d468357a components/python/imaging/patches/07-CVE-2016-9190.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/python/imaging/patches/07-CVE-2016-9190.patch Mon Nov 21 13:24:12 2016 -0800 @@ -0,0 +1,26 @@ +CVE-2016-9190 +https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2016-9190 + +Python Imaging allows context-dependent attackers to execute arbitrary code +by using the "crafted image file" approach, related to an "Insecure Sign +Extension" issue affecting the ImagingNew in Storage.c component. + +Code changes based on those found upstream for Pillow at: + +https://github.com/python-pillow/Pillow/pull/2146/commits/5d8a0be45aad78c5a22c8d099118ee26ef8144af +for: + libImaging/Storage.c + +--- Imaging-1.1.7/libImaging/Storage.c.orig 2016-11-21 07:38:52.301251099 +0000 ++++ Imaging-1.1.7/libImaging/Storage.c 2016-11-21 07:40:39.795030452 +0000 +@@ -369,6 +369,10 @@ + } else + bytes = strlen(mode); /* close enough */ + ++ if (xsize < 0 || ysize < 0) { ++ return (Imaging) ImagingError_ValueError("bad image size"); ++ } ++ + if ((long) xsize * ysize * bytes <= THRESHOLD) { + im = ImagingNewBlock(mode, xsize, ysize); + if (im)