Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88bd672daf | ||
|
|
d3486362da | ||
|
|
2a66fa7f2e | ||
|
|
608bf4fef5 | ||
|
|
756fff3312 | ||
|
|
886ad5a90e | ||
|
|
0907fb13f4 | ||
|
|
c60c09280b | ||
|
|
8fb5e5035b | ||
|
|
a10d2c950a | ||
|
|
4bdc0da7ca | ||
|
|
20c0e1a19e | ||
|
|
741d8744a5 | ||
|
|
179cd1c8f9 | ||
|
|
7d296653da | ||
|
|
d25036fca7 | ||
|
|
973a4c333a | ||
|
|
521dab94c7 | ||
|
|
8b8076bdcb | ||
|
|
e25be1e33d | ||
|
|
f891baa604 | ||
|
|
cbfdde7b1f | ||
|
|
2ba5eb1cd9 | ||
|
|
a0a5b7a01d |
@ -45,6 +45,7 @@ test_script:
|
|||||||
- cd c:\pillow
|
- cd c:\pillow
|
||||||
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov'
|
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov'
|
||||||
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\%EXECUTABLE%
|
- c:\"Program Files (x86)"\"Windows Kits"\10\Debuggers\x86\gflags.exe /p /enable %PYTHON%\%EXECUTABLE%
|
||||||
|
- '%PYTHON%\%EXECUTABLE% -c "from PIL import Image"'
|
||||||
- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests'
|
- '%PYTHON%\%EXECUTABLE% -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests'
|
||||||
#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
|
#- '%PYTHON%\%EXECUTABLE% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
|
||||||
|
|
||||||
|
|||||||
@ -2,4 +2,6 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
python -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term Tests
|
python3 -c "from PIL import Image"
|
||||||
|
|
||||||
|
python3 -bb -m pytest -v -x -W always --cov PIL --cov Tests --cov-report term Tests
|
||||||
|
|||||||
1
.github/workflows/test-windows.yml
vendored
1
.github/workflows/test-windows.yml
vendored
@ -273,6 +273,7 @@ jobs:
|
|||||||
- name: Test Pillow
|
- name: Test Pillow
|
||||||
run: |
|
run: |
|
||||||
python3 selftest.py --installed
|
python3 selftest.py --installed
|
||||||
|
python3 -c "from PIL import Image"
|
||||||
python3 -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
python3 -m pytest -vx --cov PIL --cov Tests --cov-report term --cov-report xml Tests
|
||||||
|
|
||||||
- name: Upload coverage
|
- name: Upload coverage
|
||||||
|
|||||||
29
CHANGES.rst
29
CHANGES.rst
@ -2,7 +2,34 @@
|
|||||||
Changelog (Pillow)
|
Changelog (Pillow)
|
||||||
==================
|
==================
|
||||||
|
|
||||||
8.1.0 (2020-01-02)
|
8.1.2 (2021-03-06)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Fix Memory DOS in BLP (CVE-2021-27921), ICNS (CVE-2021-27922) and ICO (CVE-2021-27923) Image Plugins
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
8.1.1 (2021-03-01)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- Use more specific regex chars to prevent ReDoS. CVE-2021-25292
|
||||||
|
[hugovk]
|
||||||
|
|
||||||
|
- Fix OOB Read in TiffDecode.c, and check the tile validity before reading. CVE-2021-25291
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix negative size read in TiffDecode.c. CVE-2021-25290
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Fix OOB read in SgiRleDecode.c. CVE-2021-25293
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- Incorrect error code checking in TiffDecode.c. CVE-2021-25289
|
||||||
|
[wiredfool]
|
||||||
|
|
||||||
|
- PyModule_AddObject fix for Python 3.10 #5194
|
||||||
|
[radarhere]
|
||||||
|
|
||||||
|
8.1.0 (2021-01-02)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- Fix TIFF OOB Write error. CVE-2020-35654 #5175
|
- Fix TIFF OOB Write error. CVE-2020-35654 #5175
|
||||||
|
|||||||
BIN
Tests/images/crash-0c7e0e8e11ce787078f00b5b0ca409a167f070e0.tif
Normal file
BIN
Tests/images/crash-0c7e0e8e11ce787078f00b5b0ca409a167f070e0.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-0e16d3bfb83be87356d026d66919deaefca44dac.tif
Normal file
BIN
Tests/images/crash-0e16d3bfb83be87356d026d66919deaefca44dac.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-1152ec2d1a1a71395b6f2ce6721c38924d025bf3.tif
Normal file
BIN
Tests/images/crash-1152ec2d1a1a71395b6f2ce6721c38924d025bf3.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-1185209cf7655b5aed8ae5e77784dfdd18ab59e9.tif
Normal file
BIN
Tests/images/crash-1185209cf7655b5aed8ae5e77784dfdd18ab59e9.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-338516dbd2f0e83caddb8ce256c22db3bd6dc40f.tif
Normal file
BIN
Tests/images/crash-338516dbd2f0e83caddb8ce256c22db3bd6dc40f.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-465703f71a0f0094873a3e0e82c9f798161171b8.sgi
Normal file
BIN
Tests/images/crash-465703f71a0f0094873a3e0e82c9f798161171b8.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-4f085cc12ece8cde18758d42608bed6a2a2cfb1c.tif
Normal file
BIN
Tests/images/crash-4f085cc12ece8cde18758d42608bed6a2a2cfb1c.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-63b1dffefc8c075ddc606c0a2f5fdc15ece78863.tif
Normal file
BIN
Tests/images/crash-63b1dffefc8c075ddc606c0a2f5fdc15ece78863.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-64834657ee604b8797bf99eac6a194c124a9a8ba.sgi
Normal file
BIN
Tests/images/crash-64834657ee604b8797bf99eac6a194c124a9a8ba.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-754d9c7ec485ffb76a90eeaab191ef69a2a3a3cd.sgi
Normal file
BIN
Tests/images/crash-754d9c7ec485ffb76a90eeaab191ef69a2a3a3cd.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-86214e58da443d2b80820cff9677a38a33dcbbca.tif
Normal file
BIN
Tests/images/crash-86214e58da443d2b80820cff9677a38a33dcbbca.tif
Normal file
Binary file not shown.
BIN
Tests/images/crash-abcf1c97b8fe42a6c68f1fb0b978530c98d57ced.sgi
Normal file
BIN
Tests/images/crash-abcf1c97b8fe42a6c68f1fb0b978530c98d57ced.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-b82e64d4f3f76d7465b6af535283029eda211259.sgi
Normal file
BIN
Tests/images/crash-b82e64d4f3f76d7465b6af535283029eda211259.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-c1b2595b8b0b92cc5f38b6635e98e3a119ade807.sgi
Normal file
BIN
Tests/images/crash-c1b2595b8b0b92cc5f38b6635e98e3a119ade807.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-db8bfa78b19721225425530c5946217720d7df4e.sgi
Normal file
BIN
Tests/images/crash-db8bfa78b19721225425530c5946217720d7df4e.sgi
Normal file
Binary file not shown.
BIN
Tests/images/crash-f46f5b2f43c370fe65706c11449f567ecc345e74.tif
Normal file
BIN
Tests/images/crash-f46f5b2f43c370fe65706c11449f567ecc345e74.tif
Normal file
Binary file not shown.
BIN
Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns
Normal file
BIN
Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns
Normal file
Binary file not shown.
@ -139,3 +139,11 @@ def test_not_an_icns_file():
|
|||||||
with io.BytesIO(b"invalid\n") as fp:
|
with io.BytesIO(b"invalid\n") as fp:
|
||||||
with pytest.raises(SyntaxError):
|
with pytest.raises(SyntaxError):
|
||||||
IcnsImagePlugin.IcnsFile(fp)
|
IcnsImagePlugin.IcnsFile(fp)
|
||||||
|
|
||||||
|
|
||||||
|
def test_icns_decompression_bomb():
|
||||||
|
with pytest.raises(Image.DecompressionBombError):
|
||||||
|
im = Image.open(
|
||||||
|
"Tests/images/oom-8ed3316a4109213ca96fb8a256a0bfefdece1461.icns"
|
||||||
|
)
|
||||||
|
im.load()
|
||||||
|
|||||||
@ -11,6 +11,13 @@ from PIL import Image
|
|||||||
"Tests/images/sgi_crash.bin",
|
"Tests/images/sgi_crash.bin",
|
||||||
"Tests/images/crash-6b7f2244da6d0ae297ee0754a424213444e92778.sgi",
|
"Tests/images/crash-6b7f2244da6d0ae297ee0754a424213444e92778.sgi",
|
||||||
"Tests/images/ossfuzz-5730089102868480.sgi",
|
"Tests/images/ossfuzz-5730089102868480.sgi",
|
||||||
|
"Tests/images/crash-754d9c7ec485ffb76a90eeaab191ef69a2a3a3cd.sgi",
|
||||||
|
"Tests/images/crash-465703f71a0f0094873a3e0e82c9f798161171b8.sgi",
|
||||||
|
"Tests/images/crash-64834657ee604b8797bf99eac6a194c124a9a8ba.sgi",
|
||||||
|
"Tests/images/crash-abcf1c97b8fe42a6c68f1fb0b978530c98d57ced.sgi",
|
||||||
|
"Tests/images/crash-b82e64d4f3f76d7465b6af535283029eda211259.sgi",
|
||||||
|
"Tests/images/crash-c1b2595b8b0b92cc5f38b6635e98e3a119ade807.sgi",
|
||||||
|
"Tests/images/crash-db8bfa78b19721225425530c5946217720d7df4e.sgi",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_crashes(test_file):
|
def test_crashes(test_file):
|
||||||
|
|||||||
@ -24,6 +24,15 @@ from .helper import on_ci
|
|||||||
"Tests/images/crash_1.tif",
|
"Tests/images/crash_1.tif",
|
||||||
"Tests/images/crash_2.tif",
|
"Tests/images/crash_2.tif",
|
||||||
"Tests/images/crash-2020-10-test.tif",
|
"Tests/images/crash-2020-10-test.tif",
|
||||||
|
"Tests/images/crash-0c7e0e8e11ce787078f00b5b0ca409a167f070e0.tif",
|
||||||
|
"Tests/images/crash-0e16d3bfb83be87356d026d66919deaefca44dac.tif",
|
||||||
|
"Tests/images/crash-1152ec2d1a1a71395b6f2ce6721c38924d025bf3.tif",
|
||||||
|
"Tests/images/crash-1185209cf7655b5aed8ae5e77784dfdd18ab59e9.tif",
|
||||||
|
"Tests/images/crash-338516dbd2f0e83caddb8ce256c22db3bd6dc40f.tif",
|
||||||
|
"Tests/images/crash-4f085cc12ece8cde18758d42608bed6a2a2cfb1c.tif",
|
||||||
|
"Tests/images/crash-86214e58da443d2b80820cff9677a38a33dcbbca.tif",
|
||||||
|
"Tests/images/crash-f46f5b2f43c370fe65706c11449f567ecc345e74.tif",
|
||||||
|
"Tests/images/crash-63b1dffefc8c075ddc606c0a2f5fdc15ece78863.tif",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@pytest.mark.filterwarnings("ignore:Possibly corrupt EXIF data")
|
@pytest.mark.filterwarnings("ignore:Possibly corrupt EXIF data")
|
||||||
|
|||||||
@ -312,3 +312,7 @@ def setup(app):
|
|||||||
app.add_js_file("js/script.js")
|
app.add_js_file("js/script.js")
|
||||||
app.add_css_file("css/dark.css")
|
app.add_css_file("css/dark.css")
|
||||||
app.add_css_file("css/light.css")
|
app.add_css_file("css/light.css")
|
||||||
|
|
||||||
|
|
||||||
|
# GitHub repo for sphinx-issues
|
||||||
|
issues_github_path = "python-pillow/Pillow"
|
||||||
|
|||||||
@ -74,7 +74,7 @@ Security
|
|||||||
|
|
||||||
This release includes security fixes.
|
This release includes security fixes.
|
||||||
|
|
||||||
* :cve:`CVE-2020-10177` Fix multiple OOB reads in FLI decoding
|
* :cve:`CVE-2020-10177` Fix multiple out-of-bounds reads in FLI decoding
|
||||||
* :cve:`CVE-2020-10378` Fix bounds overflow in PCX decoding
|
* :cve:`CVE-2020-10378` Fix bounds overflow in PCX decoding
|
||||||
* :cve:`CVE-2020-10379` Fix two buffer overflows in TIFF decoding
|
* :cve:`CVE-2020-10379` Fix two buffer overflows in TIFF decoding
|
||||||
* :cve:`CVE-2020-10994` Fix bounds overflow in JPEG 2000 decoding
|
* :cve:`CVE-2020-10994` Fix bounds overflow in JPEG 2000 decoding
|
||||||
|
|||||||
@ -18,7 +18,7 @@ vulnerability introduced in FreeType 2.6 (:cve:`CVE-2020-15999`).
|
|||||||
Makefile
|
Makefile
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
The 'install-venv' target has been deprecated.
|
The ``install-venv`` target has been deprecated.
|
||||||
|
|
||||||
API Additions
|
API Additions
|
||||||
=============
|
=============
|
||||||
@ -46,17 +46,18 @@ The PCX image decoder used the reported image stride to calculate the row buffer
|
|||||||
rather than calculating it from the image size. This issue dates back to the PIL fork.
|
rather than calculating it from the image size. This issue dates back to the PIL fork.
|
||||||
Thanks to Google's `OSS-Fuzz`_ project for finding this.
|
Thanks to Google's `OSS-Fuzz`_ project for finding this.
|
||||||
|
|
||||||
* :cve:`CVE-2020-35654` Fix TIFF OOB Write error
|
* :cve:`CVE-2020-35654` Fix TIFF out-of-bounds write error
|
||||||
|
|
||||||
OOB Write in TiffDecode.c when reading corrupt YCbCr files in some LibTIFF versions
|
Out-of-bounds write in ``TiffDecode.c`` when reading corrupt YCbCr files in some
|
||||||
(4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases LibTIFF's
|
LibTIFF versions (4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases
|
||||||
interpretation of the file is different when reading in RGBA mode, leading to an Out of
|
LibTIFF's interpretation of the file is different when reading in RGBA mode, leading to
|
||||||
bounds write in TiffDecode.c. This potentially affects Pillow versions from 6.0.0 to
|
an out-of-bounds write in ``TiffDecode.c``. This potentially affects Pillow versions
|
||||||
8.0.1, depending on the version of LibTIFF. This was reported through `Tidelift`_.
|
from 6.0.0 to 8.0.1, depending on the version of LibTIFF. This was reported through
|
||||||
|
`Tidelift`_.
|
||||||
|
|
||||||
* :cve:`CVE-2020-35655` Fix for SGI Decode buffer overrun
|
* :cve:`CVE-2020-35655` Fix for SGI Decode buffer overrun
|
||||||
|
|
||||||
4 byte read overflow in SGIRleDecode.c, where the code was not correctly checking the
|
4 byte read overflow in ``SgiRleDecode.c``, where the code was not correctly checking the
|
||||||
offsets and length tables. Independently reported through `Tidelift`_ and Google's
|
offsets and length tables. Independently reported through `Tidelift`_ and Google's
|
||||||
`OSS-Fuzz`_. This vulnerability covers Pillow versions 4.3.0->8.0.1.
|
`OSS-Fuzz`_. This vulnerability covers Pillow versions 4.3.0->8.0.1.
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ Other Changes
|
|||||||
Makefile
|
Makefile
|
||||||
^^^^^^^^
|
^^^^^^^^
|
||||||
|
|
||||||
The 'co' target has been removed.
|
The ``co`` target has been removed.
|
||||||
|
|
||||||
PyPy wheels
|
PyPy wheels
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
|||||||
27
docs/releasenotes/8.1.1.rst
Normal file
27
docs/releasenotes/8.1.1.rst
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
8.1.1
|
||||||
|
-----
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
:cve:`CVE-2021-25289`: The previous fix for :cve:`CVE-2020-35654` was insufficient
|
||||||
|
due to incorrect error checking in ``TiffDecode.c``.
|
||||||
|
|
||||||
|
:cve:`CVE-2021-25290`: In ``TiffDecode.c``, there is a negative-offset ``memcpy``
|
||||||
|
with an invalid size.
|
||||||
|
|
||||||
|
:cve:`CVE-2021-25291`: In ``TiffDecode.c``, invalid tile boundaries could lead to
|
||||||
|
an out-of-bounds read in ``TIFFReadRGBATile``.
|
||||||
|
|
||||||
|
:cve:`CVE-2021-25292`: The PDF parser has a catastrophic backtracking regex
|
||||||
|
that could be used as a DOS attack.
|
||||||
|
|
||||||
|
:cve:`CVE-2021-25293`: There is an out-of-bounds read in ``SgiRleDecode.c``,
|
||||||
|
since Pillow 4.3.0.
|
||||||
|
|
||||||
|
|
||||||
|
Other Changes
|
||||||
|
=============
|
||||||
|
|
||||||
|
A crash with the feature flags for libimagequant, libjpeg-turbo, WebP and XCB on
|
||||||
|
unreleased Python 3.10 has been fixed (:issue:`5193`).
|
||||||
12
docs/releasenotes/8.1.2.rst
Normal file
12
docs/releasenotes/8.1.2.rst
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
8.1.2
|
||||||
|
-----
|
||||||
|
|
||||||
|
Security
|
||||||
|
========
|
||||||
|
|
||||||
|
There is an exhaustion of memory DOS in the BLP (:cve:`CVE-2021-27921`),
|
||||||
|
ICNS (:cve:`CVE-2021-27922`) and ICO (:cve:`CVE-2021-27923`) container formats
|
||||||
|
where Pillow did not properly check the reported size of the contained image.
|
||||||
|
These images could cause arbitrarily large memory allocations. This was reported
|
||||||
|
by Jiayi Lin, Luke Shaffer, Xinran Xie, and Akshay Ajayan of
|
||||||
|
`Arizona State University <https://www.asu.edu/>`_.
|
||||||
@ -14,6 +14,8 @@ expected to be backported to earlier versions.
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
|
8.1.2
|
||||||
|
8.1.1
|
||||||
8.1.0
|
8.1.0
|
||||||
8.0.1
|
8.0.1
|
||||||
8.0.0
|
8.0.0
|
||||||
|
|||||||
@ -353,6 +353,7 @@ class BLP1Decoder(_BLPBaseDecoder):
|
|||||||
data = jpeg_header + data
|
data = jpeg_header + data
|
||||||
data = BytesIO(data)
|
data = BytesIO(data)
|
||||||
image = JpegImageFile(data)
|
image = JpegImageFile(data)
|
||||||
|
Image._decompression_bomb_check(image.size)
|
||||||
self.tile = image.tile # :/
|
self.tile = image.tile # :/
|
||||||
self.fd = image.fp
|
self.fd = image.fp
|
||||||
self.mode = image.mode
|
self.mode = image.mode
|
||||||
|
|||||||
@ -105,6 +105,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||||||
if sig[:8] == b"\x89PNG\x0d\x0a\x1a\x0a":
|
if sig[:8] == b"\x89PNG\x0d\x0a\x1a\x0a":
|
||||||
fobj.seek(start)
|
fobj.seek(start)
|
||||||
im = PngImagePlugin.PngImageFile(fobj)
|
im = PngImagePlugin.PngImageFile(fobj)
|
||||||
|
Image._decompression_bomb_check(im.size)
|
||||||
return {"RGBA": im}
|
return {"RGBA": im}
|
||||||
elif (
|
elif (
|
||||||
sig[:4] == b"\xff\x4f\xff\x51"
|
sig[:4] == b"\xff\x4f\xff\x51"
|
||||||
@ -121,6 +122,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
|||||||
jp2kstream = fobj.read(length)
|
jp2kstream = fobj.read(length)
|
||||||
f = io.BytesIO(jp2kstream)
|
f = io.BytesIO(jp2kstream)
|
||||||
im = Jpeg2KImagePlugin.Jpeg2KImageFile(f)
|
im = Jpeg2KImagePlugin.Jpeg2KImageFile(f)
|
||||||
|
Image._decompression_bomb_check(im.size)
|
||||||
if im.mode != "RGBA":
|
if im.mode != "RGBA":
|
||||||
im = im.convert("RGBA")
|
im = im.convert("RGBA")
|
||||||
return {"RGBA": im}
|
return {"RGBA": im}
|
||||||
|
|||||||
@ -178,6 +178,7 @@ class IcoFile:
|
|||||||
if data[:8] == PngImagePlugin._MAGIC:
|
if data[:8] == PngImagePlugin._MAGIC:
|
||||||
# png frame
|
# png frame
|
||||||
im = PngImagePlugin.PngImageFile(self.buf)
|
im = PngImagePlugin.PngImageFile(self.buf)
|
||||||
|
Image._decompression_bomb_check(im.size)
|
||||||
else:
|
else:
|
||||||
# XOR + AND mask bmp frame
|
# XOR + AND mask bmp frame
|
||||||
im = BmpImagePlugin.DibImageFile(self.buf)
|
im = BmpImagePlugin.DibImageFile(self.buf)
|
||||||
|
|||||||
@ -580,8 +580,9 @@ class PdfParser:
|
|||||||
whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]"
|
whitespace_or_hex = br"[\000\011\012\014\015\0400-9a-fA-F]"
|
||||||
whitespace_optional = whitespace + b"*"
|
whitespace_optional = whitespace + b"*"
|
||||||
whitespace_mandatory = whitespace + b"+"
|
whitespace_mandatory = whitespace + b"+"
|
||||||
|
whitespace_optional_no_nl = br"[\000\011\014\015\040]*" # no "\012" aka "\n"
|
||||||
newline_only = br"[\r\n]+"
|
newline_only = br"[\r\n]+"
|
||||||
newline = whitespace_optional + newline_only + whitespace_optional
|
newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl
|
||||||
re_trailer_end = re.compile(
|
re_trailer_end = re.compile(
|
||||||
whitespace_mandatory
|
whitespace_mandatory
|
||||||
+ br"trailer"
|
+ br"trailer"
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
# Master version for Pillow
|
# Master version for Pillow
|
||||||
__version__ = "8.1.0"
|
__version__ = "8.1.2"
|
||||||
|
|||||||
@ -4172,26 +4172,33 @@ setup_module(PyObject* m) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PyObject *have_libjpegturbo;
|
||||||
#ifdef LIBJPEG_TURBO_VERSION
|
#ifdef LIBJPEG_TURBO_VERSION
|
||||||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_True);
|
have_libjpegturbo = Py_True;
|
||||||
#define tostr1(a) #a
|
#define tostr1(a) #a
|
||||||
#define tostr(a) tostr1(a)
|
#define tostr(a) tostr1(a)
|
||||||
PyDict_SetItemString(d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
|
PyDict_SetItemString(
|
||||||
#undef tostr
|
d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
|
||||||
#undef tostr1
|
#undef tostr
|
||||||
|
#undef tostr1
|
||||||
#else
|
#else
|
||||||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_False);
|
have_libjpegturbo = Py_False;
|
||||||
#endif
|
#endif
|
||||||
|
Py_INCREF(have_libjpegturbo);
|
||||||
|
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", have_libjpegturbo);
|
||||||
|
|
||||||
|
PyObject *have_libimagequant;
|
||||||
#ifdef HAVE_LIBIMAGEQUANT
|
#ifdef HAVE_LIBIMAGEQUANT
|
||||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_True);
|
have_libimagequant = Py_True;
|
||||||
{
|
{
|
||||||
extern const char* ImagingImageQuantVersion(void);
|
extern const char* ImagingImageQuantVersion(void);
|
||||||
PyDict_SetItemString(d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion()));
|
PyDict_SetItemString(d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion()));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_False);
|
have_libimagequant = Py_False;
|
||||||
#endif
|
#endif
|
||||||
|
Py_INCREF(have_libimagequant);
|
||||||
|
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", have_libimagequant);
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
/* zip encoding strategies */
|
/* zip encoding strategies */
|
||||||
@ -4222,11 +4229,14 @@ setup_module(PyObject* m) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PyObject *have_xcb;
|
||||||
#ifdef HAVE_XCB
|
#ifdef HAVE_XCB
|
||||||
PyModule_AddObject(m, "HAVE_XCB", Py_True);
|
have_xcb = Py_True;
|
||||||
#else
|
#else
|
||||||
PyModule_AddObject(m, "HAVE_XCB", Py_False);
|
have_xcb = Py_False;
|
||||||
#endif
|
#endif
|
||||||
|
Py_INCREF(have_xcb);
|
||||||
|
PyModule_AddObject(m, "HAVE_XCB", have_xcb);
|
||||||
|
|
||||||
PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version));
|
PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version));
|
||||||
|
|
||||||
|
|||||||
16
src/_webp.c
16
src/_webp.c
@ -861,19 +861,25 @@ static PyMethodDef webpMethods[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
void addMuxFlagToModule(PyObject* m) {
|
void addMuxFlagToModule(PyObject* m) {
|
||||||
|
PyObject *have_webpmux;
|
||||||
#ifdef HAVE_WEBPMUX
|
#ifdef HAVE_WEBPMUX
|
||||||
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_True);
|
have_webpmux = Py_True;
|
||||||
#else
|
#else
|
||||||
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_False);
|
have_webpmux = Py_False;
|
||||||
#endif
|
#endif
|
||||||
|
Py_INCREF(have_webpmux);
|
||||||
|
PyModule_AddObject(m, "HAVE_WEBPMUX", have_webpmux);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addAnimFlagToModule(PyObject* m) {
|
void addAnimFlagToModule(PyObject *m) {
|
||||||
|
PyObject *have_webpanim;
|
||||||
#ifdef HAVE_WEBPANIM
|
#ifdef HAVE_WEBPANIM
|
||||||
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_True);
|
have_webpanim = Py_True;
|
||||||
#else
|
#else
|
||||||
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_False);
|
have_webpanim = Py_False;
|
||||||
#endif
|
#endif
|
||||||
|
Py_INCREF(have_webpanim);
|
||||||
|
PyModule_AddObject(m, "HAVE_WEBPANIM", have_webpanim);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTransparencyFlagToModule(PyObject* m) {
|
void addTransparencyFlagToModule(PyObject* m) {
|
||||||
|
|||||||
@ -25,13 +25,59 @@ 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, int xsize)
|
/*
|
||||||
|
SgiRleDecoding is done in a single channel row oriented set of RLE chunks.
|
||||||
|
|
||||||
|
* The file is arranged as
|
||||||
|
- SGI Header
|
||||||
|
- Rle Offset Table
|
||||||
|
- Rle Length Table
|
||||||
|
- Scanline Data
|
||||||
|
|
||||||
|
* Each RLE atom is c->bpc bytes wide (1 or 2)
|
||||||
|
|
||||||
|
* Each RLE Chunk is [specifier atom] [ 1 or n data atoms ]
|
||||||
|
|
||||||
|
* Copy Atoms are a byte with the high bit set, and the low 7 are
|
||||||
|
the number of bytes to copy from the source to the
|
||||||
|
destination. e.g.
|
||||||
|
|
||||||
|
CBBBBBBBB or 0CHLHLHLHLHLHL (B=byte, H/L = Hi low bytes)
|
||||||
|
|
||||||
|
* Run atoms do not have the high bit set, and the low 7 bits are
|
||||||
|
the number of copies of the next atom to copy to the
|
||||||
|
destination. e.g.:
|
||||||
|
|
||||||
|
RB -> BBBBB or RHL -> HLHLHLHLHL
|
||||||
|
|
||||||
|
The upshot of this is, there is no way to determine the required
|
||||||
|
length of the input buffer from reloffset and rlelength without
|
||||||
|
going through the data at that scan line.
|
||||||
|
|
||||||
|
Furthermore, there's no requirement that individual scan lines
|
||||||
|
pointed to from the rleoffset table are in any sort of order or
|
||||||
|
used only once, or even disjoint. There's also no requirement that
|
||||||
|
all of the data in the scan line area of the image file be used
|
||||||
|
|
||||||
|
*/
|
||||||
|
static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize, UINT8* end_of_buffer)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* n here is the number of rlechunks
|
||||||
|
* z is the number of channels, for calculating the interleave
|
||||||
|
* offset to go to RGBA style pixels
|
||||||
|
* xsize is the row width
|
||||||
|
* end_of_buffer is the address of the end of the input buffer
|
||||||
|
*/
|
||||||
|
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
for (;n > 0; n--)
|
for (;n > 0; n--)
|
||||||
{
|
{
|
||||||
|
if (src > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
pixel = *src++;
|
pixel = *src++;
|
||||||
if (n == 1 && pixel != 0) {
|
if (n == 1 && pixel != 0) {
|
||||||
return n;
|
return n;
|
||||||
@ -45,6 +91,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
|||||||
}
|
}
|
||||||
x += count;
|
x += count;
|
||||||
if (pixel & RLE_COPY_FLAG) {
|
if (pixel & RLE_COPY_FLAG) {
|
||||||
|
if (src + count > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
while(count--) {
|
while(count--) {
|
||||||
*dest = *src++;
|
*dest = *src++;
|
||||||
dest += z;
|
dest += z;
|
||||||
@ -52,6 +101,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
|||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (src > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
pixel = *src++;
|
pixel = *src++;
|
||||||
while (count--) {
|
while (count--) {
|
||||||
*dest = pixel;
|
*dest = pixel;
|
||||||
@ -63,14 +115,16 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize, UINT8* end_of_buffer)
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
for (;n > 0; n--)
|
for (;n > 0; n--)
|
||||||
{
|
{
|
||||||
|
if (src + 1 > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
pixel = src[1];
|
pixel = src[1];
|
||||||
src+=2;
|
src+=2;
|
||||||
if (n == 1 && pixel != 0) {
|
if (n == 1 && pixel != 0) {
|
||||||
@ -85,6 +139,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
|||||||
}
|
}
|
||||||
x += count;
|
x += count;
|
||||||
if (pixel & RLE_COPY_FLAG) {
|
if (pixel & RLE_COPY_FLAG) {
|
||||||
|
if (src + 2 * count > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
while(count--) {
|
while(count--) {
|
||||||
memcpy(dest, src, 2);
|
memcpy(dest, src, 2);
|
||||||
src += 2;
|
src += 2;
|
||||||
@ -92,6 +149,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (src + 2 > end_of_buffer) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
while (count--) {
|
while (count--) {
|
||||||
memcpy(dest, src, 2);
|
memcpy(dest, src, 2);
|
||||||
dest += z * 2;
|
dest += z * 2;
|
||||||
@ -141,7 +201,10 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
_imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
|
_imaging_seek_pyFd(state->fd, SGI_HEADER_SIZE, SEEK_SET);
|
||||||
_imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize);
|
if (_imaging_read_pyFd(state->fd, (char*)ptr, c->bufsize) != c->bufsize) {
|
||||||
|
state->errcode = IMAGING_CODEC_UNKNOWN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* decoder initialization */
|
/* decoder initialization */
|
||||||
@ -175,8 +238,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]);
|
read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->count += c->tablen * sizeof(UINT32) * 2;
|
|
||||||
|
|
||||||
/* read compressed rows */
|
/* read compressed rows */
|
||||||
for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep)
|
for (c->rowno = 0; c->rowno < im->ysize; c->rowno++, state->y += state->ystep)
|
||||||
{
|
{
|
||||||
@ -184,19 +245,21 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
{
|
{
|
||||||
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
|
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
|
||||||
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
|
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
|
||||||
c->rleoffset -= SGI_HEADER_SIZE;
|
|
||||||
|
|
||||||
if (c->rleoffset + c->rlelength > c->bufsize) {
|
// Check for underflow of rleoffset-SGI_HEADER_SIZE
|
||||||
|
if (c->rleoffset < SGI_HEADER_SIZE) {
|
||||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
goto sgi_finish_decode;
|
goto sgi_finish_decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->rleoffset -= SGI_HEADER_SIZE;
|
||||||
|
|
||||||
/* row decompression */
|
/* row decompression */
|
||||||
if (c->bpc ==1) {
|
if (c->bpc ==1) {
|
||||||
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
status = expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize);
|
status = expandrow2(&state->buffer[c->channo * 2], &ptr[c->rleoffset], c->rlelength, im->bands, im->xsize, &ptr[c->bufsize-1]);
|
||||||
}
|
}
|
||||||
if (status == -1) {
|
if (status == -1) {
|
||||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||||
@ -205,7 +268,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
goto sgi_finish_decode;
|
goto sgi_finish_decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->count += c->rlelength;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store decompressed data in image */
|
/* store decompressed data in image */
|
||||||
@ -213,8 +275,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->bufsize++;
|
|
||||||
|
|
||||||
sgi_finish_decode: ;
|
sgi_finish_decode: ;
|
||||||
|
|
||||||
free(c->starttab);
|
free(c->starttab);
|
||||||
@ -224,5 +284,5 @@ sgi_finish_decode: ;
|
|||||||
state->errcode=err;
|
state->errcode=err;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return state->count - c->bufsize;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,10 @@ tsize_t _tiffReadProc(thandle_t hdata, tdata_t buf, tsize_t size) {
|
|||||||
TRACE(("_tiffReadProc: %d \n", (int)size));
|
TRACE(("_tiffReadProc: %d \n", (int)size));
|
||||||
dump_state(state);
|
dump_state(state);
|
||||||
|
|
||||||
|
if (state->loc > state->eof) {
|
||||||
|
TIFFError("_tiffReadProc", "Invalid Read at loc %d, eof: %d", state->loc, state->eof);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc);
|
to_read = min(size, min(state->size, (tsize_t)state->eof) - (tsize_t)state->loc);
|
||||||
TRACE(("to_read: %d\n", (int)to_read));
|
TRACE(("to_read: %d\n", (int)to_read));
|
||||||
|
|
||||||
@ -250,7 +254,7 @@ int _decodeStripYCbCr(Imaging im, ImagingCodecState state, TIFF *tiff) {
|
|||||||
img.row_offset = state->y;
|
img.row_offset = state->y;
|
||||||
rows_to_read = min(rows_per_strip, img.height - state->y);
|
rows_to_read = min(rows_per_strip, img.height - state->y);
|
||||||
|
|
||||||
if (TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read) == -1) {
|
if (!TIFFRGBAImageGet(&img, (UINT32 *)state->buffer, img.width, rows_to_read)) {
|
||||||
TRACE(("Decode Error, y: %d\n", state->y ));
|
TRACE(("Decode Error, y: %d\n", state->y ));
|
||||||
state->errcode = IMAGING_CODEC_BROKEN;
|
state->errcode = IMAGING_CODEC_BROKEN;
|
||||||
goto decodeycbcr_err;
|
goto decodeycbcr_err;
|
||||||
@ -475,6 +479,15 @@ int ImagingLibTiffDecode(Imaging im, ImagingCodecState state, UINT8* buffer, Py_
|
|||||||
|
|
||||||
for (y = state->yoff; y < state->ysize; y += tile_length) {
|
for (y = state->yoff; y < state->ysize; y += tile_length) {
|
||||||
for (x = state->xoff; x < state->xsize; x += tile_width) {
|
for (x = state->xoff; x < state->xsize; x += tile_width) {
|
||||||
|
/* Sanity Check. Apparently in some cases, the TiffReadRGBA* functions
|
||||||
|
have a different view of the size of the tiff than we're getting from
|
||||||
|
other functions. So, we need to check here.
|
||||||
|
*/
|
||||||
|
if (!TIFFCheckTile(tiff, x, y, 0, 0)) {
|
||||||
|
TRACE(("Check Tile Error, Tile at %dx%d\n", x, y));
|
||||||
|
state->errcode = IMAGING_CODEC_BROKEN;
|
||||||
|
goto decode_err;
|
||||||
|
}
|
||||||
if (isYCbCr) {
|
if (isYCbCr) {
|
||||||
/* To avoid dealing with YCbCr subsampling, let libtiff handle it */
|
/* To avoid dealing with YCbCr subsampling, let libtiff handle it */
|
||||||
if (!TIFFReadRGBATile(tiff, x, y, (UINT32 *)state->buffer)) {
|
if (!TIFFReadRGBATile(tiff, x, y, (UINT32 *)state->buffer)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user