Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b28c176817 | ||
|
|
3f73d9b680 | ||
|
|
98101c0463 | ||
|
|
6ce889a573 | ||
|
|
9cf752a697 | ||
|
|
58e7501998 | ||
|
|
fe7b41b438 | ||
|
|
d4663806a8 |
16
CHANGES.rst
16
CHANGES.rst
@ -1,6 +1,22 @@
|
|||||||
Changelog (Pillow)
|
Changelog (Pillow)
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
3.3.3 (2016-10-04)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fix fix for map.c overflow #2151
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
3.3.2 (2016-10-03)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fix negative image sizes in Storage.c #2105
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix integer overflow in map.c #2105
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
|
||||||
3.3.1 (2016-08-18)
|
3.3.1 (2016-08-18)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|||||||
@ -154,7 +154,7 @@ class ImageFile(Image.Image):
|
|||||||
if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
|
if d == "raw" and a[0] == self.mode and a[0] in Image._MAPMODES:
|
||||||
try:
|
try:
|
||||||
if hasattr(Image.core, "map"):
|
if hasattr(Image.core, "map"):
|
||||||
# use built-in mapper
|
# use built-in mapper WIN32 only
|
||||||
self.map = Image.core.map(self.filename)
|
self.map = Image.core.map(self.filename)
|
||||||
self.map.seek(o)
|
self.map.seek(o)
|
||||||
self.im = self.map.readimage(
|
self.im = self.map.readimage(
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
# ;-)
|
# ;-)
|
||||||
|
|
||||||
VERSION = '1.1.7' # PIL version
|
VERSION = '1.1.7' # PIL version
|
||||||
PILLOW_VERSION = '3.3.1' # Pillow
|
PILLOW_VERSION = '3.3.3' # Pillow
|
||||||
|
|
||||||
_plugins = ['BmpImagePlugin',
|
_plugins = ['BmpImagePlugin',
|
||||||
'BufrStubImagePlugin',
|
'BufrStubImagePlugin',
|
||||||
|
|||||||
BIN
Tests/images/l2rgb_read.bmp
Normal file
BIN
Tests/images/l2rgb_read.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 57 B |
BIN
Tests/images/negative_size.ppm
Executable file
BIN
Tests/images/negative_size.ppm
Executable file
Binary file not shown.
@ -44,6 +44,18 @@ class TestFilePpm(PillowTestCase):
|
|||||||
self.assertRaises(ValueError, lambda: Image.open(path))
|
self.assertRaises(ValueError, lambda: Image.open(path))
|
||||||
|
|
||||||
|
|
||||||
|
def test_neg_ppm(self):
|
||||||
|
"""test_neg_ppm
|
||||||
|
|
||||||
|
Storage.c accepted negative values for xsize, ysize.
|
||||||
|
open_ppm is a core debugging item that doesn't check any parameters for
|
||||||
|
sanity.
|
||||||
|
"""
|
||||||
|
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
Image.core.open_ppm('Tests/images/negative_size.ppm')
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|||||||
28
Tests/test_map.py
Normal file
28
Tests/test_map.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from helper import PillowTestCase, unittest
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(sys.platform.startswith('win32'), "Win32 does not call map_buffer")
|
||||||
|
class TestMap(PillowTestCase):
|
||||||
|
def test_overflow(self):
|
||||||
|
# There is the potential to overflow comparisons in map.c
|
||||||
|
# if there are > SIZE_MAX bytes in the image or if
|
||||||
|
# the file encodes an offset that makes
|
||||||
|
# (offset + size(bytes)) > SIZE_MAX
|
||||||
|
|
||||||
|
# Note that this image triggers the decompression bomb warning:
|
||||||
|
max_pixels = Image.MAX_IMAGE_PIXELS
|
||||||
|
Image.MAX_IMAGE_PIXELS = None
|
||||||
|
|
||||||
|
# This image hits the offset test.
|
||||||
|
im = Image.open('Tests/images/l2rgb_read.bmp')
|
||||||
|
with self.assertRaises((ValueError, MemoryError, IOError)):
|
||||||
|
im.load()
|
||||||
|
|
||||||
|
Image.MAX_IMAGE_PIXELS = max_pixels
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
@ -71,7 +71,7 @@
|
|||||||
* See the README file for information on usage and redistribution.
|
* See the README file for information on usage and redistribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PILLOW_VERSION "3.3.1"
|
#define PILLOW_VERSION "3.3.3"
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
version: 3.3.1.{build}
|
version: 3.3.3.{build}
|
||||||
clone_folder: c:\pillow
|
clone_folder: c:\pillow
|
||||||
init:
|
init:
|
||||||
- ECHO %PYTHON%
|
- ECHO %PYTHON%
|
||||||
|
|||||||
40
docs/releasenotes/3.3.2.rst
Normal file
40
docs/releasenotes/3.3.2.rst
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
3.3.2
|
||||||
|
=====
|
||||||
|
|
||||||
|
Integer overflow in Map.c
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Pillow prior to 3.3.2 may experience integer overflow errors in map.c
|
||||||
|
when reading specially crafted image files. This may lead to memory
|
||||||
|
disclosure or corruption.
|
||||||
|
|
||||||
|
Specifically, when parameters from the image are passed into
|
||||||
|
``Image.core.map_buffer``, the size of the image was calculated with
|
||||||
|
``xsize``*``ysize``*``bytes_per_pixel``. This will overflow if the
|
||||||
|
result is larger than SIZE_MAX. This is possible on a 32-bit system.
|
||||||
|
|
||||||
|
Furthermore this ``size`` value was added to a potentially attacker
|
||||||
|
provided ``offset`` value and compared to the size of the buffer
|
||||||
|
without checking for overflow or negative values.
|
||||||
|
|
||||||
|
These values were then used for creating pointers, at which point
|
||||||
|
Pillow could read the memory and include it in other images. The image
|
||||||
|
was marked readonly, so Pillow would not ordinarily write to that
|
||||||
|
memory without duplicating the image first.
|
||||||
|
|
||||||
|
This issue was found by Cris Neckar at Divergent Security.
|
||||||
|
|
||||||
|
Sign Extension in Storage.c
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Pillow prior to 3.3.2 and PIL 1.1.7 (at least) do not check for
|
||||||
|
negative image sizes in ``ImagingNew`` in ``Storage.c``. A negative
|
||||||
|
image size can lead to a smaller allocation than expected, leading to
|
||||||
|
arbitrary writes.
|
||||||
|
|
||||||
|
This issue was found by Cris Neckar at Divergent Security.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -6,6 +6,7 @@ Release Notes
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
3.3.2
|
||||||
3.3.0
|
3.3.0
|
||||||
3.2.0
|
3.2.0
|
||||||
3.1.2
|
3.1.2
|
||||||
|
|||||||
@ -406,6 +406,10 @@ ImagingNew(const char* mode, int xsize, int ysize)
|
|||||||
} else
|
} else
|
||||||
bytes = strlen(mode); /* close enough */
|
bytes = strlen(mode); /* close enough */
|
||||||
|
|
||||||
|
if (xsize < 0 || ysize < 0) {
|
||||||
|
return (Imaging) ImagingError_ValueError("bad image size");
|
||||||
|
}
|
||||||
|
|
||||||
if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) {
|
if ((int64_t) xsize * (int64_t) ysize <= THRESHOLD / bytes) {
|
||||||
im = ImagingNewBlock(mode, xsize, ysize);
|
im = ImagingNewBlock(mode, xsize, ysize);
|
||||||
if (im)
|
if (im)
|
||||||
|
|||||||
10
map.c
10
map.c
@ -342,8 +342,18 @@ PyImaging_MapBuffer(PyObject* self, PyObject* args)
|
|||||||
stride = xsize * 4;
|
stride = xsize * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ysize > INT_MAX / stride) {
|
||||||
|
PyErr_SetString(PyExc_MemoryError, "Integer overflow in ysize");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
size = (Py_ssize_t) ysize * stride;
|
size = (Py_ssize_t) ysize * stride;
|
||||||
|
|
||||||
|
if (offset > PY_SSIZE_T_MAX - size) {
|
||||||
|
PyErr_SetString(PyExc_MemoryError, "Integer overflow in offset");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* check buffer size */
|
/* check buffer size */
|
||||||
if (PyImaging_GetBuffer(target, &view) < 0)
|
if (PyImaging_GetBuffer(target, &view) < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user