--- /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 <ctype.h>
+
+-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)