Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a45c8583ff | ||
|
|
83efad4875 | ||
|
|
4820f79e01 | ||
|
|
4e2def2539 | ||
|
|
a79b65c47c | ||
|
|
93b22b846e | ||
|
|
a09acd0dec | ||
|
|
774e53bb13 | ||
|
|
8892aecfbf | ||
|
|
46c35f06b1 | ||
|
|
f269b49cff | ||
|
|
cc04ee7b5c | ||
|
|
48908c94e8 | ||
|
|
c8d620416f | ||
|
|
bde3e9cfc9 | ||
|
|
c77171fea2 | ||
|
|
9fa34ecc2e | ||
|
|
738bbd2641 | ||
|
|
71ffb52320 | ||
|
|
fe38d93250 | ||
|
|
a9126faa7a | ||
|
|
89d6c84ba0 | ||
|
|
fe8ba74f93 | ||
|
|
7a0a2e966c | ||
|
|
6e0f07bbe3 | ||
|
|
39d26d3f90 | ||
|
|
ee9e21aff1 | ||
|
|
efcfb91b71 | ||
|
|
f97c4ddb0a | ||
|
|
b78edcc9e4 |
@ -18,6 +18,8 @@ environment:
|
|||||||
PIP_DIR: bin
|
PIP_DIR: bin
|
||||||
VENV: YES
|
VENV: YES
|
||||||
- PYTHON: C:/Python27-x64
|
- PYTHON: C:/Python27-x64
|
||||||
|
- PYTHON: C:/Python38
|
||||||
|
- PYTHON: C:/Python38-x64
|
||||||
- PYTHON: C:/Python37
|
- PYTHON: C:/Python37
|
||||||
- PYTHON: C:/Python27
|
- PYTHON: C:/Python27
|
||||||
- PYTHON: C:/Python37-x64
|
- PYTHON: C:/Python37-x64
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
parameters:
|
parameters:
|
||||||
docker: '' # defaults for any parameters that aren't specified
|
docker: '' # defaults for any parameters that aren't specified
|
||||||
dockerTag: 'master'
|
dockerTag: '6.2.x'
|
||||||
name: ''
|
name: ''
|
||||||
vmImage: 'Ubuntu-16.04'
|
vmImage: 'Ubuntu-16.04'
|
||||||
|
|
||||||
|
|||||||
30
.travis.yml
30
.travis.yml
@ -20,6 +20,9 @@ matrix:
|
|||||||
name: "PyPy2 Xenial"
|
name: "PyPy2 Xenial"
|
||||||
- python: "pypy3"
|
- python: "pypy3"
|
||||||
name: "PyPy3 Xenial"
|
name: "PyPy3 Xenial"
|
||||||
|
- python: "3.8"
|
||||||
|
name: "3.8 Xenial"
|
||||||
|
services: xvfb
|
||||||
- python: '3.7'
|
- python: '3.7'
|
||||||
name: "3.7 Xenial"
|
name: "3.7 Xenial"
|
||||||
- python: '2.7'
|
- python: '2.7'
|
||||||
@ -33,20 +36,19 @@ matrix:
|
|||||||
- python: '3.5'
|
- python: '3.5'
|
||||||
name: "3.5 Xenial PYTHONOPTIMIZE=2"
|
name: "3.5 Xenial PYTHONOPTIMIZE=2"
|
||||||
env: PYTHONOPTIMIZE=2
|
env: PYTHONOPTIMIZE=2
|
||||||
- python: "3.8-dev"
|
- env: DOCKER="alpine" DOCKER_TAG="6.2.x"
|
||||||
name: "3.8-dev Xenial"
|
- env: DOCKER="arch" DOCKER_TAG="6.2.x" # contains PyQt5
|
||||||
- env: DOCKER="alpine" DOCKER_TAG="master"
|
- env: DOCKER="ubuntu-16.04-xenial-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="arch" DOCKER_TAG="master" # contains PyQt5
|
- env: DOCKER="ubuntu-18.04-bionic-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="ubuntu-16.04-xenial-amd64" DOCKER_TAG="master"
|
- env: DOCKER="debian-9-stretch-x86" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="ubuntu-18.04-bionic-amd64" DOCKER_TAG="master"
|
- env: DOCKER="debian-10-buster-x86" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="debian-9-stretch-x86" DOCKER_TAG="master"
|
- env: DOCKER="centos-6-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="debian-10-buster-x86" DOCKER_TAG="master"
|
- env: DOCKER="centos-7-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="centos-6-amd64" DOCKER_TAG="master"
|
- env: DOCKER="centos-8-amd64" DOCKER_TAG="master"
|
||||||
- env: DOCKER="centos-7-amd64" DOCKER_TAG="master"
|
- env: DOCKER="amazon-1-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="amazon-1-amd64" DOCKER_TAG="master"
|
- env: DOCKER="amazon-2-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="amazon-2-amd64" DOCKER_TAG="master"
|
- env: DOCKER="fedora-30-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="fedora-29-amd64" DOCKER_TAG="master"
|
- env: DOCKER="fedora-31-amd64" DOCKER_TAG="6.2.x"
|
||||||
- env: DOCKER="fedora-30-amd64" DOCKER_TAG="master"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|||||||
26
CHANGES.rst
26
CHANGES.rst
@ -2,11 +2,35 @@
|
|||||||
Changelog (Pillow)
|
Changelog (Pillow)
|
||||||
==================
|
==================
|
||||||
|
|
||||||
6.2.0 (2019-10-01)
|
6.2.2 (2020-01-02)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- This is the last Pillow release to support Python 2.7 #3642
|
- This is the last Pillow release to support Python 2.7 #3642
|
||||||
|
|
||||||
|
- Overflow checks for realloc for tiff decoding. CVE TBD
|
||||||
|
[wiredfool, radarhere]
|
||||||
|
|
||||||
|
- Catch SGI buffer overrun. CVE TBD
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- Catch PCX P mode buffer overrun. CVE TBD
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- Catch FLI buffer overrun. CVE TBD
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
- Raise an error for an invalid number of bands in FPX image. CVE-2019-19911
|
||||||
|
[wiredfool, radarhere]
|
||||||
|
|
||||||
|
6.2.1 (2019-10-21)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Add support for Python 3.8 #4141
|
||||||
|
[hugovk]
|
||||||
|
|
||||||
|
6.2.0 (2019-10-01)
|
||||||
|
------------------
|
||||||
|
|
||||||
- Catch buffer overruns #4104
|
- Catch buffer overruns #4104
|
||||||
[radarhere]
|
[radarhere]
|
||||||
|
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@ -5,7 +5,7 @@ The Python Imaging Library (PIL) is
|
|||||||
|
|
||||||
Pillow is the friendly PIL fork. It is
|
Pillow is the friendly PIL fork. It is
|
||||||
|
|
||||||
Copyright © 2010-2019 by Alex Clark and contributors
|
Copyright © 2010-2020 by Alex Clark and contributors
|
||||||
|
|
||||||
Like PIL, Pillow is licensed under the open source PIL Software License:
|
Like PIL, Pillow is licensed under the open source PIL Software License:
|
||||||
|
|
||||||
|
|||||||
BIN
Tests/images/fli_overrun2.bin
Normal file
BIN
Tests/images/fli_overrun2.bin
Normal file
Binary file not shown.
BIN
Tests/images/input_bw_five_bands.fpx
Normal file
BIN
Tests/images/input_bw_five_bands.fpx
Normal file
Binary file not shown.
BIN
Tests/images/pcx_overrun2.bin
Normal file
BIN
Tests/images/pcx_overrun2.bin
Normal file
Binary file not shown.
BIN
Tests/images/sgi_overrun_expandrow.bin
Normal file
BIN
Tests/images/sgi_overrun_expandrow.bin
Normal file
Binary file not shown.
BIN
Tests/images/sgi_overrun_expandrow2.bin
Normal file
BIN
Tests/images/sgi_overrun_expandrow2.bin
Normal file
Binary file not shown.
BIN
Tests/images/tiff_overflow_rows_per_strip.tif
Normal file
BIN
Tests/images/tiff_overflow_rows_per_strip.tif
Normal file
Binary file not shown.
@ -1,3 +1,5 @@
|
|||||||
|
from PIL import Image
|
||||||
|
|
||||||
from .helper import PillowTestCase, unittest
|
from .helper import PillowTestCase, unittest
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -18,3 +20,7 @@ class TestFileFpx(PillowTestCase):
|
|||||||
# Test a valid OLE file, but not an FPX file
|
# Test a valid OLE file, but not an FPX file
|
||||||
ole_file = "Tests/images/test-ole-file.doc"
|
ole_file = "Tests/images/test-ole-file.doc"
|
||||||
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file)
|
self.assertRaises(SyntaxError, FpxImagePlugin.FpxImageFile, ole_file)
|
||||||
|
|
||||||
|
def test_fpx_invalid_number_of_bands(self):
|
||||||
|
with self.assertRaisesRegex(IOError, "Invalid number of bands"):
|
||||||
|
Image.open("Tests/images/input_bw_five_bands.fpx")
|
||||||
|
|||||||
@ -870,3 +870,13 @@ class TestFileLibTiff(LibTiffTestCase):
|
|||||||
out.seek(0)
|
out.seek(0)
|
||||||
with Image.open(out) as im:
|
with Image.open(out) as im:
|
||||||
im.load()
|
im.load()
|
||||||
|
|
||||||
|
def test_realloc_overflow(self):
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = True
|
||||||
|
with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im:
|
||||||
|
with self.assertRaises(IOError) as e:
|
||||||
|
im.load()
|
||||||
|
|
||||||
|
# Assert that the error code is IMAGING_CODEC_MEMORY
|
||||||
|
self.assertEqual(str(e.exception), "-9")
|
||||||
|
TiffImagePlugin.READ_LIBTIFF = False
|
||||||
|
|||||||
@ -590,7 +590,14 @@ class TestImage(PillowTestCase):
|
|||||||
self.assertFalse(fp.closed)
|
self.assertFalse(fp.closed)
|
||||||
|
|
||||||
def test_overrun(self):
|
def test_overrun(self):
|
||||||
for file in ["fli_overrun.bin", "sgi_overrun.bin", "pcx_overrun.bin"]:
|
for file in [
|
||||||
|
"fli_overrun.bin",
|
||||||
|
"sgi_overrun.bin",
|
||||||
|
"sgi_overrun_expandrow.bin",
|
||||||
|
"sgi_overrun_expandrow2.bin",
|
||||||
|
"pcx_overrun.bin",
|
||||||
|
"pcx_overrun2.bin",
|
||||||
|
]:
|
||||||
im = Image.open(os.path.join("Tests/images", file))
|
im = Image.open(os.path.join("Tests/images", file))
|
||||||
try:
|
try:
|
||||||
im.load()
|
im.load()
|
||||||
@ -598,6 +605,13 @@ class TestImage(PillowTestCase):
|
|||||||
except IOError as e:
|
except IOError as e:
|
||||||
self.assertEqual(str(e), "buffer overrun when reading image file")
|
self.assertEqual(str(e), "buffer overrun when reading image file")
|
||||||
|
|
||||||
|
with Image.open("Tests/images/fli_overrun2.bin") as im:
|
||||||
|
try:
|
||||||
|
im.seek(1)
|
||||||
|
self.assertFail()
|
||||||
|
except IOError as e:
|
||||||
|
self.assertEqual(str(e), "buffer overrun when reading image file")
|
||||||
|
|
||||||
|
|
||||||
class MockEncoder(object):
|
class MockEncoder(object):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@ -51,6 +51,11 @@ jobs:
|
|||||||
docker: 'centos-7-amd64'
|
docker: 'centos-7-amd64'
|
||||||
name: 'centos_7_amd64'
|
name: 'centos_7_amd64'
|
||||||
|
|
||||||
|
- template: .azure-pipelines/jobs/test-docker.yml
|
||||||
|
parameters:
|
||||||
|
docker: 'centos-8-amd64'
|
||||||
|
name: 'centos_8_amd64'
|
||||||
|
|
||||||
- template: .azure-pipelines/jobs/test-docker.yml
|
- template: .azure-pipelines/jobs/test-docker.yml
|
||||||
parameters:
|
parameters:
|
||||||
docker: 'amazon-1-amd64'
|
docker: 'amazon-1-amd64'
|
||||||
@ -63,10 +68,10 @@ jobs:
|
|||||||
|
|
||||||
- template: .azure-pipelines/jobs/test-docker.yml
|
- template: .azure-pipelines/jobs/test-docker.yml
|
||||||
parameters:
|
parameters:
|
||||||
docker: 'fedora-29-amd64'
|
docker: 'fedora-30-amd64'
|
||||||
name: 'fedora_29_amd64'
|
name: 'fedora_30_amd64'
|
||||||
|
|
||||||
- template: .azure-pipelines/jobs/test-docker.yml
|
- template: .azure-pipelines/jobs/test-docker.yml
|
||||||
parameters:
|
parameters:
|
||||||
docker: 'fedora-30-amd64'
|
docker: 'fedora-31-amd64'
|
||||||
name: 'fedora_30_amd64'
|
name: 'fedora_31_amd64'
|
||||||
|
|||||||
@ -5,7 +5,7 @@ The Python Imaging Library (PIL) is
|
|||||||
|
|
||||||
Pillow is the friendly PIL fork. It is
|
Pillow is the friendly PIL fork. It is
|
||||||
|
|
||||||
Copyright © 2010-2019 by Alex Clark and contributors
|
Copyright © 2010-2020 by Alex Clark and contributors
|
||||||
|
|
||||||
Like PIL, Pillow is licensed under the open source PIL
|
Like PIL, Pillow is licensed under the open source PIL
|
||||||
Software License:
|
Software License:
|
||||||
|
|||||||
@ -43,7 +43,7 @@ master_doc = "index"
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u"Pillow (PIL Fork)"
|
project = u"Pillow (PIL Fork)"
|
||||||
copyright = u"1995-2011 Fredrik Lundh, 2010-2019 Alex Clark and Contributors"
|
copyright = u"1995-2011 Fredrik Lundh, 2010-2020 Alex Clark and Contributors"
|
||||||
author = u"Fredrik Lundh, Alex Clark and Contributors"
|
author = u"Fredrik Lundh, Alex Clark and Contributors"
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
|||||||
@ -15,23 +15,25 @@ Notes
|
|||||||
|
|
||||||
.. note:: Pillow is supported on the following Python versions
|
.. note:: Pillow is supported on the following Python versions
|
||||||
|
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|**Python** |**2.4**|**2.5**|**2.6**|**2.7**|**3.2**|**3.3**|**3.4**|**3.5**|**3.6**|**3.7**|
|
|**Python** |**2.4**|**2.5**|**2.6**|**2.7**|**3.2**|**3.3**|**3.4**|**3.5**|**3.6**|**3.7**|**3.8**|
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow < 2.0.0 | Yes | Yes | Yes | Yes | | | | | | |
|
|Pillow < 2 | Yes | Yes | Yes | Yes | | | | | | | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow 2.x - 3.x | | | Yes | Yes | Yes | Yes | Yes | Yes | | |
|
|Pillow 2 - 3 | | | Yes | Yes | Yes | Yes | Yes | Yes | | | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow 4.x | | | | Yes | | Yes | Yes | Yes | Yes | |
|
|Pillow 4 | | | | Yes | | Yes | Yes | Yes | Yes | | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow 5.0.x - 5.1.x | | | | Yes | | | Yes | Yes | Yes | |
|
|Pillow 5.0 - 5.1 | | | | Yes | | | Yes | Yes | Yes | | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow 5.2.x - 5.4.x | | | | Yes | | | Yes | Yes | Yes | Yes |
|
|Pillow 5.2 - 5.4 | | | | Yes | | | Yes | Yes | Yes | Yes | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow 6.x | | | | Yes | | | | Yes | Yes | Yes |
|
|Pillow 6.0 - 6.2.0 | | | | Yes | | | | Yes | Yes | Yes | |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|Pillow >= 7.0.0 | | | | | | | | Yes | Yes | Yes |
|
|Pillow 6.2.1 | | | | Yes | | | | Yes | Yes | Yes | Yes |
|
||||||
+---------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|
|Pillow >= 7 | | | | | | | | Yes | Yes | Yes | Yes |
|
||||||
|
+-------------------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+-------+
|
||||||
|
|
||||||
Basic Installation
|
Basic Installation
|
||||||
------------------
|
------------------
|
||||||
@ -395,20 +397,22 @@ These platforms are built and tested for every change.
|
|||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| CentOS 7 | 2.7, 3.6 |x86-64 |
|
| CentOS 7 | 2.7, 3.6 |x86-64 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
|
| CentOS 8 | 2.7, 3.6 |x86-64 |
|
||||||
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| Debian 9 Stretch | 2.7, 3.5 |x86 |
|
| Debian 9 Stretch | 2.7, 3.5 |x86 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| Debian 10 Buster | 2.7, 3.7 |x86 |
|
| Debian 10 Buster | 2.7, 3.7 |x86 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| Fedora 29 | 2.7, 3.7 |x86-64 |
|
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
|
||||||
| Fedora 30 | 2.7, 3.7 |x86-64 |
|
| Fedora 30 | 2.7, 3.7 |x86-64 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| macOS 10.13 High Sierra* | 2.7, 3.5, 3.6, 3.7 |x86-64 |
|
| Fedora 31 | 2.7, 3.7 |x86-64 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| Ubuntu Linux 16.04 LTS | 2.7, 3.5, 3.6, 3.7, |x86-64 |
|
| macOS 10.13 High Sierra* | 2.7, 3.5, 3.6, 3.7, 3.8 |x86-64 |
|
||||||
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
|
| Ubuntu Linux 16.04 LTS | 2.7, 3.5, 3.6, 3.7, 3.8, |x86-64 |
|
||||||
| | PyPy, PyPy3 | |
|
| | PyPy, PyPy3 | |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
| Windows Server 2012 R2 | 2.7, 3.5, 3.6, 3.7 |x86, x86-64 |
|
| Windows Server 2012 R2 | 2.7, 3.5, 3.6, 3.7, 3.8 |x86, x86-64 |
|
||||||
| +-------------------------------+-----------------------+
|
| +-------------------------------+-----------------------+
|
||||||
| | PyPy, 3.7/MinGW |x86 |
|
| | PyPy, 3.7/MinGW |x86 |
|
||||||
+----------------------------------+-------------------------------+-----------------------+
|
+----------------------------------+-------------------------------+-----------------------+
|
||||||
|
|||||||
@ -62,14 +62,6 @@ shared instance of ``Image.Exif``.
|
|||||||
Deprecations
|
Deprecations
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
Python 2.7
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
Python 2.7 reaches end-of-life on 2020-01-01.
|
|
||||||
|
|
||||||
Pillow 7.0.0 will be released on 2020-01-01 and will drop support for Python
|
|
||||||
2.7, making Pillow 6.2.x the last release series to support Python 2.
|
|
||||||
|
|
||||||
Image.frombuffer
|
Image.frombuffer
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -77,6 +69,27 @@ There has been a longstanding warning that the defaults of ``Image.frombuffer``
|
|||||||
may change in the future for the "raw" decoder. The change will now take place
|
may change in the future for the "raw" decoder. The change will now take place
|
||||||
in Pillow 7.0.
|
in Pillow 7.0.
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
This release catches several buffer overruns, as well as addressing
|
||||||
|
CVE-2019-16865. The CVE is regarding DOS problems, such as consuming large
|
||||||
|
amounts of memory, or taking a large amount of time to process an image.
|
||||||
|
|
||||||
|
In RawDecode.c, an error is now thrown if skip is calculated to be less than
|
||||||
|
zero. It is intended to skip padding between lines, not to go backwards.
|
||||||
|
|
||||||
|
In PsdImagePlugin, if the combined sizes of the individual parts is larger than
|
||||||
|
the declared size of the extra data field, then it looked for the next layer by
|
||||||
|
seeking backwards. This is now corrected by seeking to (the start of the layer
|
||||||
|
+ the size of the extra data field) instead of (the read parts of the layer +
|
||||||
|
the rest of the layer).
|
||||||
|
|
||||||
|
Decompression bomb checks have been added to GIF and ICO formats.
|
||||||
|
|
||||||
|
An error is now raised if a TIFF dimension is a string, rather than trying to
|
||||||
|
perform operations on it.
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|||||||
26
docs/releasenotes/6.2.1.rst
Normal file
26
docs/releasenotes/6.2.1.rst
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
6.2.1
|
||||||
|
-----
|
||||||
|
|
||||||
|
API Changes
|
||||||
|
===========
|
||||||
|
|
||||||
|
Deprecations
|
||||||
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Python 2.7
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
Python 2.7 reaches end-of-life on 2020-01-01.
|
||||||
|
|
||||||
|
Pillow 7.0.0 will be released on 2020-01-01 and will drop support for Python
|
||||||
|
2.7, making Pillow 6.2.x the last release series to support Python 2.
|
||||||
|
|
||||||
|
Other Changes
|
||||||
|
=============
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Support added for Python 3.8
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Pillow 6.2.1 supports Python 3.8.
|
||||||
18
docs/releasenotes/6.2.2.rst
Normal file
18
docs/releasenotes/6.2.2.rst
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
6.2.2
|
||||||
|
-----
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
This release addresses several security problems {CVEs TBD), as well as addressing
|
||||||
|
CVE-2019-19911.
|
||||||
|
|
||||||
|
CVE-2019-19911 is regarding FPX images. If an image reports that it has a large number
|
||||||
|
of bands, a large amount of resources will be used when trying to process the
|
||||||
|
image. This is fixed by limiting the number of bands to those usable by Pillow.
|
||||||
|
|
||||||
|
Buffer overruns were found when processing an SGI, PCX or FLI image. Checks
|
||||||
|
have been added to prevent this.
|
||||||
|
|
||||||
|
Overflow checks have been added when calculating the size of a memory block to
|
||||||
|
be reallocated in the processing of a TIFF image.
|
||||||
@ -6,6 +6,8 @@ Release Notes
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
6.2.2
|
||||||
|
6.2.1
|
||||||
6.2.0
|
6.2.0
|
||||||
6.1.0
|
6.1.0
|
||||||
6.0.0
|
6.0.0
|
||||||
|
|||||||
3
setup.py
3
setup.py
@ -24,7 +24,7 @@ from setuptools import Extension, setup
|
|||||||
# comment this out to disable multi threaded builds.
|
# comment this out to disable multi threaded builds.
|
||||||
import mp_compile
|
import mp_compile
|
||||||
|
|
||||||
if sys.platform == "win32" and sys.version_info >= (3, 8):
|
if sys.platform == "win32" and sys.version_info >= (3, 9):
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"Pillow does not yet support Python {}.{} and does not yet provide "
|
"Pillow does not yet support Python {}.{} and does not yet provide "
|
||||||
"prebuilt Windows binaries. We do not recommend building from "
|
"prebuilt Windows binaries. We do not recommend building from "
|
||||||
@ -867,6 +867,7 @@ try:
|
|||||||
"Programming Language :: Python :: 3.5",
|
"Programming Language :: Python :: 3.5",
|
||||||
"Programming Language :: Python :: 3.6",
|
"Programming Language :: Python :: 3.6",
|
||||||
"Programming Language :: Python :: 3.7",
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
"Programming Language :: Python :: Implementation :: CPython",
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
"Programming Language :: Python :: Implementation :: PyPy",
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
"Topic :: Multimedia :: Graphics",
|
"Topic :: Multimedia :: Graphics",
|
||||||
|
|||||||
@ -119,7 +119,7 @@ def decode_dxt3(data):
|
|||||||
bits = struct.unpack_from("<8B", block)
|
bits = struct.unpack_from("<8B", block)
|
||||||
color0, color1 = struct.unpack_from("<HH", block, 8)
|
color0, color1 = struct.unpack_from("<HH", block, 8)
|
||||||
|
|
||||||
code, = struct.unpack_from("<I", block, 12)
|
(code,) = struct.unpack_from("<I", block, 12)
|
||||||
|
|
||||||
r0, g0, b0 = unpack_565(color0)
|
r0, g0, b0 = unpack_565(color0)
|
||||||
r1, g1, b1 = unpack_565(color1)
|
r1, g1, b1 = unpack_565(color1)
|
||||||
@ -177,7 +177,7 @@ def decode_dxt5(data):
|
|||||||
|
|
||||||
color0, color1 = struct.unpack_from("<HH", block, 8)
|
color0, color1 = struct.unpack_from("<HH", block, 8)
|
||||||
|
|
||||||
code, = struct.unpack_from("<I", block, 12)
|
(code,) = struct.unpack_from("<I", block, 12)
|
||||||
|
|
||||||
r0, g0, b0 = unpack_565(color0)
|
r0, g0, b0 = unpack_565(color0)
|
||||||
r1, g1, b1 = unpack_565(color1)
|
r1, g1, b1 = unpack_565(color1)
|
||||||
@ -255,19 +255,19 @@ class BlpImageFile(ImageFile.ImageFile):
|
|||||||
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
self.tile = [(decoder, (0, 0) + self.size, 0, (self.mode, 0, 1))]
|
||||||
|
|
||||||
def _read_blp_header(self):
|
def _read_blp_header(self):
|
||||||
self._blp_compression, = struct.unpack("<i", self.fp.read(4))
|
(self._blp_compression,) = struct.unpack("<i", self.fp.read(4))
|
||||||
|
|
||||||
self._blp_encoding, = struct.unpack("<b", self.fp.read(1))
|
(self._blp_encoding,) = struct.unpack("<b", self.fp.read(1))
|
||||||
self._blp_alpha_depth, = struct.unpack("<b", self.fp.read(1))
|
(self._blp_alpha_depth,) = struct.unpack("<b", self.fp.read(1))
|
||||||
self._blp_alpha_encoding, = struct.unpack("<b", self.fp.read(1))
|
(self._blp_alpha_encoding,) = struct.unpack("<b", self.fp.read(1))
|
||||||
self._blp_mips, = struct.unpack("<b", self.fp.read(1))
|
(self._blp_mips,) = struct.unpack("<b", self.fp.read(1))
|
||||||
|
|
||||||
self._size = struct.unpack("<II", self.fp.read(8))
|
self._size = struct.unpack("<II", self.fp.read(8))
|
||||||
|
|
||||||
if self.magic == b"BLP1":
|
if self.magic == b"BLP1":
|
||||||
# Only present for BLP1
|
# Only present for BLP1
|
||||||
self._blp_encoding, = struct.unpack("<i", self.fp.read(4))
|
(self._blp_encoding,) = struct.unpack("<i", self.fp.read(4))
|
||||||
self._blp_subtype, = struct.unpack("<i", self.fp.read(4))
|
(self._blp_subtype,) = struct.unpack("<i", self.fp.read(4))
|
||||||
|
|
||||||
self._blp_offsets = struct.unpack("<16I", self.fp.read(16 * 4))
|
self._blp_offsets = struct.unpack("<16I", self.fp.read(16 * 4))
|
||||||
self._blp_lengths = struct.unpack("<16I", self.fp.read(16 * 4))
|
self._blp_lengths = struct.unpack("<16I", self.fp.read(16 * 4))
|
||||||
@ -297,19 +297,19 @@ class _BLPBaseDecoder(ImageFile.PyDecoder):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _read_blp_header(self):
|
def _read_blp_header(self):
|
||||||
self._blp_compression, = struct.unpack("<i", self.fd.read(4))
|
(self._blp_compression,) = struct.unpack("<i", self.fd.read(4))
|
||||||
|
|
||||||
self._blp_encoding, = struct.unpack("<b", self.fd.read(1))
|
(self._blp_encoding,) = struct.unpack("<b", self.fd.read(1))
|
||||||
self._blp_alpha_depth, = struct.unpack("<b", self.fd.read(1))
|
(self._blp_alpha_depth,) = struct.unpack("<b", self.fd.read(1))
|
||||||
self._blp_alpha_encoding, = struct.unpack("<b", self.fd.read(1))
|
(self._blp_alpha_encoding,) = struct.unpack("<b", self.fd.read(1))
|
||||||
self._blp_mips, = struct.unpack("<b", self.fd.read(1))
|
(self._blp_mips,) = struct.unpack("<b", self.fd.read(1))
|
||||||
|
|
||||||
self.size = struct.unpack("<II", self.fd.read(8))
|
self.size = struct.unpack("<II", self.fd.read(8))
|
||||||
|
|
||||||
if self.magic == b"BLP1":
|
if self.magic == b"BLP1":
|
||||||
# Only present for BLP1
|
# Only present for BLP1
|
||||||
self._blp_encoding, = struct.unpack("<i", self.fd.read(4))
|
(self._blp_encoding,) = struct.unpack("<i", self.fd.read(4))
|
||||||
self._blp_subtype, = struct.unpack("<i", self.fd.read(4))
|
(self._blp_subtype,) = struct.unpack("<i", self.fd.read(4))
|
||||||
|
|
||||||
self._blp_offsets = struct.unpack("<16I", self.fd.read(16 * 4))
|
self._blp_offsets = struct.unpack("<16I", self.fd.read(16 * 4))
|
||||||
self._blp_lengths = struct.unpack("<16I", self.fd.read(16 * 4))
|
self._blp_lengths = struct.unpack("<16I", self.fd.read(16 * 4))
|
||||||
@ -327,7 +327,7 @@ class BLP1Decoder(_BLPBaseDecoder):
|
|||||||
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
|
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
offset, = struct.unpack("<B", _data.read(1))
|
(offset,) = struct.unpack("<B", _data.read(1))
|
||||||
except struct.error:
|
except struct.error:
|
||||||
break
|
break
|
||||||
b, g, r, a = palette[offset]
|
b, g, r, a = palette[offset]
|
||||||
@ -346,7 +346,7 @@ class BLP1Decoder(_BLPBaseDecoder):
|
|||||||
def _decode_jpeg_stream(self):
|
def _decode_jpeg_stream(self):
|
||||||
from PIL.JpegImagePlugin import JpegImageFile
|
from PIL.JpegImagePlugin import JpegImageFile
|
||||||
|
|
||||||
jpeg_header_size, = struct.unpack("<I", self.fd.read(4))
|
(jpeg_header_size,) = struct.unpack("<I", self.fd.read(4))
|
||||||
jpeg_header = self.fd.read(jpeg_header_size)
|
jpeg_header = self.fd.read(jpeg_header_size)
|
||||||
self.fd.read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
|
self.fd.read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
|
||||||
data = self.fd.read(self._blp_lengths[0])
|
data = self.fd.read(self._blp_lengths[0])
|
||||||
@ -372,7 +372,7 @@ class BLP2Decoder(_BLPBaseDecoder):
|
|||||||
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
|
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
offset, = struct.unpack("<B", _data.read(1))
|
(offset,) = struct.unpack("<B", _data.read(1))
|
||||||
except struct.error:
|
except struct.error:
|
||||||
break
|
break
|
||||||
b, g, r, a = palette[offset]
|
b, g, r, a = palette[offset]
|
||||||
|
|||||||
@ -122,7 +122,7 @@ class DdsImageFile(ImageFile.ImageFile):
|
|||||||
# pixel format
|
# pixel format
|
||||||
pfsize, pfflags = struct.unpack("<2I", header.read(8))
|
pfsize, pfflags = struct.unpack("<2I", header.read(8))
|
||||||
fourcc = header.read(4)
|
fourcc = header.read(4)
|
||||||
bitcount, = struct.unpack("<I", header.read(4))
|
(bitcount,) = struct.unpack("<I", header.read(4))
|
||||||
masks = struct.unpack("<4I", header.read(16))
|
masks = struct.unpack("<4I", header.read(16))
|
||||||
if pfflags & 0x40:
|
if pfflags & 0x40:
|
||||||
# DDPF_RGB - Texture contains uncompressed RGB data
|
# DDPF_RGB - Texture contains uncompressed RGB data
|
||||||
|
|||||||
@ -104,7 +104,10 @@ class FpxImageFile(ImageFile.ImageFile):
|
|||||||
s = prop[0x2000002 | id]
|
s = prop[0x2000002 | id]
|
||||||
|
|
||||||
colors = []
|
colors = []
|
||||||
for i in range(i32(s, 4)):
|
bands = i32(s, 4)
|
||||||
|
if bands > 4:
|
||||||
|
raise IOError("Invalid number of bands")
|
||||||
|
for i in range(bands):
|
||||||
# note: for now, we ignore the "uncalibrated" flag
|
# note: for now, we ignore the "uncalibrated" flag
|
||||||
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
|
colors.append(i32(s, 8 + i * 4) & 0x7FFFFFFF)
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ class FtexImageFile(ImageFile.ImageFile):
|
|||||||
|
|
||||||
format, where = struct.unpack("<2i", self.fp.read(8))
|
format, where = struct.unpack("<2i", self.fp.read(8))
|
||||||
self.fp.seek(where)
|
self.fp.seek(where)
|
||||||
mipmap_size, = struct.unpack("<i", self.fp.read(4))
|
(mipmap_size,) = struct.unpack("<i", self.fp.read(4))
|
||||||
|
|
||||||
data = self.fp.read(mipmap_size)
|
data = self.fp.read(mipmap_size)
|
||||||
|
|
||||||
|
|||||||
@ -3238,7 +3238,7 @@ class Exif(MutableMapping):
|
|||||||
continue
|
continue
|
||||||
size = count * unit_size
|
size = count * unit_size
|
||||||
if size > 4:
|
if size > 4:
|
||||||
offset, = struct.unpack("<L", data)
|
(offset,) = struct.unpack("<L", data)
|
||||||
data = ifd_data[offset - 12 : offset + size - 12]
|
data = ifd_data[offset - 12 : offset + size - 12]
|
||||||
else:
|
else:
|
||||||
data = data[:size]
|
data = data[:size]
|
||||||
@ -3268,7 +3268,7 @@ class Exif(MutableMapping):
|
|||||||
)
|
)
|
||||||
if ifd_tag == 0x1101:
|
if ifd_tag == 0x1101:
|
||||||
# CameraInfo
|
# CameraInfo
|
||||||
offset, = struct.unpack(">L", data)
|
(offset,) = struct.unpack(">L", data)
|
||||||
self.fp.seek(offset)
|
self.fp.seek(offset)
|
||||||
|
|
||||||
camerainfo = {"ModelID": self.fp.read(4)}
|
camerainfo = {"ModelID": self.fp.read(4)}
|
||||||
|
|||||||
@ -484,7 +484,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||||||
else:
|
else:
|
||||||
raise SyntaxError("not a TIFF IFD")
|
raise SyntaxError("not a TIFF IFD")
|
||||||
self.reset()
|
self.reset()
|
||||||
self.next, = self._unpack("L", ifh[4:])
|
(self.next,) = self._unpack("L", ifh[4:])
|
||||||
self._legacy_api = False
|
self._legacy_api = False
|
||||||
|
|
||||||
prefix = property(lambda self: self._prefix)
|
prefix = property(lambda self: self._prefix)
|
||||||
@ -595,7 +595,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||||||
]: # rationals
|
]: # rationals
|
||||||
values = (values,)
|
values = (values,)
|
||||||
try:
|
try:
|
||||||
dest[tag], = values
|
(dest[tag],) = values
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# We've got a builtin tag with 1 expected entry
|
# We've got a builtin tag with 1 expected entry
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
@ -765,7 +765,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||||||
size = count * unit_size
|
size = count * unit_size
|
||||||
if size > 4:
|
if size > 4:
|
||||||
here = fp.tell()
|
here = fp.tell()
|
||||||
offset, = self._unpack("L", data)
|
(offset,) = self._unpack("L", data)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
print(
|
print(
|
||||||
"Tag Location: %s - Data Location: %s" % (here, offset),
|
"Tag Location: %s - Data Location: %s" % (here, offset),
|
||||||
@ -797,7 +797,7 @@ class ImageFileDirectory_v2(MutableMapping):
|
|||||||
else:
|
else:
|
||||||
print("- value:", self[tag])
|
print("- value:", self[tag])
|
||||||
|
|
||||||
self.next, = self._unpack("L", self._ensure_read(fp, 4))
|
(self.next,) = self._unpack("L", self._ensure_read(fp, 4))
|
||||||
except IOError as msg:
|
except IOError as msg:
|
||||||
warnings.warn(str(msg))
|
warnings.warn(str(msg))
|
||||||
return
|
return
|
||||||
@ -1809,11 +1809,11 @@ class AppendingTiffWriter:
|
|||||||
return self.f.write(data)
|
return self.f.write(data)
|
||||||
|
|
||||||
def readShort(self):
|
def readShort(self):
|
||||||
value, = struct.unpack(self.shortFmt, self.f.read(2))
|
(value,) = struct.unpack(self.shortFmt, self.f.read(2))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def readLong(self):
|
def readLong(self):
|
||||||
value, = struct.unpack(self.longFmt, self.f.read(4))
|
(value,) = struct.unpack(self.longFmt, self.f.read(4))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def rewriteLastShortToLong(self, value):
|
def rewriteLastShortToLong(self, value):
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
# Master version for Pillow
|
# Master version for Pillow
|
||||||
__version__ = "6.2.0"
|
__version__ = "6.2.2"
|
||||||
|
|||||||
@ -40,8 +40,7 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* We don't decode anything unless we have a full chunk in the
|
/* We don't decode anything unless we have a full chunk in the
|
||||||
input buffer (on the other hand, the Python part of the driver
|
input buffer */
|
||||||
makes sure this is always the case) */
|
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|
||||||
@ -52,6 +51,10 @@ ImagingFliDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||||||
/* Make sure this is a frame chunk. The Python driver takes
|
/* Make sure this is a frame chunk. The Python driver takes
|
||||||
case of other chunk types. */
|
case of other chunk types. */
|
||||||
|
|
||||||
|
if (bytes < 8) {
|
||||||
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (I16(ptr+4) != 0xF1FA) {
|
if (I16(ptr+4) != 0xF1FA) {
|
||||||
state->errcode = IMAGING_CODEC_UNKNOWN;
|
state->errcode = IMAGING_CODEC_UNKNOWN;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -25,6 +25,9 @@ ImagingPcxDecode(Imaging im, ImagingCodecState state, UINT8* buf, Py_ssize_t byt
|
|||||||
if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) {
|
if (strcmp(im->mode, "1") == 0 && state->xsize > state->bytes * 8) {
|
||||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
return -1;
|
return -1;
|
||||||
|
} else if (strcmp(im->mode, "P") == 0 && state->xsize > state->bytes) {
|
||||||
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = buf;
|
ptr = buf;
|
||||||
|
|||||||
@ -25,7 +25,7 @@ static void read4B(UINT32* dest, UINT8* buf)
|
|||||||
*dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
|
*dest = (UINT32)((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
@ -37,6 +37,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
|||||||
count = pixel & RLE_MAX_RUN;
|
count = pixel & RLE_MAX_RUN;
|
||||||
if (!count)
|
if (!count)
|
||||||
return count;
|
return count;
|
||||||
|
if (count > xsize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (pixel & RLE_COPY_FLAG) {
|
if (pixel & RLE_COPY_FLAG) {
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*dest = *src++;
|
*dest = *src++;
|
||||||
@ -56,7 +59,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z)
|
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
@ -70,6 +73,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z)
|
|||||||
count = pixel & RLE_MAX_RUN;
|
count = pixel & RLE_MAX_RUN;
|
||||||
if (!count)
|
if (!count)
|
||||||
return count;
|
return count;
|
||||||
|
if (count > xsize) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
if (pixel & RLE_COPY_FLAG) {
|
if (pixel & RLE_COPY_FLAG) {
|
||||||
while(count--) {
|
while(count--) {
|
||||||
memcpy(dest, src, 2);
|
memcpy(dest, src, 2);
|
||||||
@ -96,6 +102,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
UINT8 *ptr;
|
UINT8 *ptr;
|
||||||
SGISTATE *c;
|
SGISTATE *c;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int status;
|
||||||
|
|
||||||
/* Get all data from File descriptor */
|
/* Get all data from File descriptor */
|
||||||
c = (SGISTATE*)state->context;
|
c = (SGISTATE*)state->context;
|
||||||
@ -164,12 +171,16 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
|
|
||||||
/* row decompression */
|
/* row decompression */
|
||||||
if (c->bpc ==1) {
|
if (c->bpc ==1) {
|
||||||
if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))
|
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
||||||
goto sgi_finish_decode;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands))
|
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
||||||
goto sgi_finish_decode;
|
}
|
||||||
|
if (status == -1) {
|
||||||
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
|
return -1;
|
||||||
|
} else if (status == 1) {
|
||||||
|
goto sgi_finish_decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->count += c->rlelength;
|
state->count += c->rlelength;
|
||||||
|
|||||||
@ -353,16 +353,18 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||||||
|
|
||||||
// We could use TIFFTileSize, but for YCbCr data it returns subsampled data size
|
// We could use TIFFTileSize, but for YCbCr data it returns subsampled data size
|
||||||
row_byte_size = (tile_width * state->bits + 7) / 8;
|
row_byte_size = (tile_width * state->bits + 7) / 8;
|
||||||
state->bytes = row_byte_size * tile_length;
|
|
||||||
|
|
||||||
/* overflow check for malloc */
|
/* overflow check for realloc */
|
||||||
if (state->bytes > INT_MAX - 1) {
|
if (INT_MAX / row_byte_size < tile_length) {
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
TIFFClose(tiff);
|
TIFFClose(tiff);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->bytes = row_byte_size * tile_length;
|
||||||
|
|
||||||
/* realloc to fit whole tile */
|
/* realloc to fit whole tile */
|
||||||
|
/* malloc check above */
|
||||||
new_data = realloc (state->buffer, state->bytes);
|
new_data = realloc (state->buffer, state->bytes);
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
@ -415,11 +417,20 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||||||
|
|
||||||
// We could use TIFFStripSize, but for YCbCr data it returns subsampled data size
|
// We could use TIFFStripSize, but for YCbCr data it returns subsampled data size
|
||||||
row_byte_size = (state->xsize * state->bits + 7) / 8;
|
row_byte_size = (state->xsize * state->bits + 7) / 8;
|
||||||
|
|
||||||
|
/* overflow check for realloc */
|
||||||
|
if (INT_MAX / row_byte_size < rows_per_strip) {
|
||||||
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
TIFFClose(tiff);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
state->bytes = rows_per_strip * row_byte_size;
|
state->bytes = rows_per_strip * row_byte_size;
|
||||||
|
|
||||||
TRACE(("StripSize: %d \n", state->bytes));
|
TRACE(("StripSize: %d \n", state->bytes));
|
||||||
|
|
||||||
/* realloc to fit whole strip */
|
/* realloc to fit whole strip */
|
||||||
|
/* malloc check above */
|
||||||
new_data = realloc (state->buffer, state->bytes);
|
new_data = realloc (state->buffer, state->bytes);
|
||||||
if (!new_data) {
|
if (!new_data) {
|
||||||
state->errcode = IMAGING_CODEC_MEMORY;
|
state->errcode = IMAGING_CODEC_MEMORY;
|
||||||
|
|||||||
2
tox.ini
2
tox.ini
@ -6,7 +6,7 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist =
|
envlist =
|
||||||
lint
|
lint
|
||||||
py{27,35,36,37}
|
py{27,35,36,37,38}
|
||||||
minversion = 1.9
|
minversion = 1.9
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
|
|||||||
@ -10,6 +10,7 @@ pythons = {
|
|||||||
"36": {"compiler": 7.1, "vc": 2015},
|
"36": {"compiler": 7.1, "vc": 2015},
|
||||||
"pypy3": {"compiler": 7.1, "vc": 2015},
|
"pypy3": {"compiler": 7.1, "vc": 2015},
|
||||||
"37": {"compiler": 7.1, "vc": 2015},
|
"37": {"compiler": 7.1, "vc": 2015},
|
||||||
|
"38": {"compiler": 7.1, "vc": 2015},
|
||||||
}
|
}
|
||||||
|
|
||||||
VIRT_BASE = "c:/vp/"
|
VIRT_BASE = "c:/vp/"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user