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
|
||||
- '%PYTHON%\%EXECUTABLE% -m pip install pytest pytest-cov'
|
||||
- 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% test-installed.py -v -s %TEST_OPTIONS%' TODO TEST_OPTIONS with pytest?
|
||||
|
||||
|
||||
@ -2,4 +2,6 @@
|
||||
|
||||
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
|
||||
run: |
|
||||
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
|
||||
|
||||
- name: Upload coverage
|
||||
|
||||
29
CHANGES.rst
29
CHANGES.rst
@ -2,7 +2,34 @@
|
||||
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
|
||||
|
||||
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 pytest.raises(SyntaxError):
|
||||
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/crash-6b7f2244da6d0ae297ee0754a424213444e92778.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):
|
||||
|
||||
@ -24,6 +24,15 @@ from .helper import on_ci
|
||||
"Tests/images/crash_1.tif",
|
||||
"Tests/images/crash_2.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")
|
||||
|
||||
@ -312,3 +312,7 @@ def setup(app):
|
||||
app.add_js_file("js/script.js")
|
||||
app.add_css_file("css/dark.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.
|
||||
|
||||
* :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-10379` Fix two buffer overflows in TIFF 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
|
||||
^^^^^^^^
|
||||
|
||||
The 'install-venv' target has been deprecated.
|
||||
The ``install-venv`` target has been deprecated.
|
||||
|
||||
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.
|
||||
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
|
||||
(4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases LibTIFF's
|
||||
interpretation of the file is different when reading in RGBA mode, leading to an Out of
|
||||
bounds write in TiffDecode.c. This potentially affects Pillow versions from 6.0.0 to
|
||||
8.0.1, depending on the version of LibTIFF. This was reported through `Tidelift`_.
|
||||
Out-of-bounds write in ``TiffDecode.c`` when reading corrupt YCbCr files in some
|
||||
LibTIFF versions (4.1.0/Ubuntu 20.04, but not 4.0.9/Ubuntu 18.04). In some cases
|
||||
LibTIFF's interpretation of the file is different when reading in RGBA mode, leading to
|
||||
an out-of-bounds write in ``TiffDecode.c``. This potentially affects Pillow versions
|
||||
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
|
||||
|
||||
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
|
||||
`OSS-Fuzz`_. This vulnerability covers Pillow versions 4.3.0->8.0.1.
|
||||
|
||||
@ -75,7 +76,7 @@ Other Changes
|
||||
Makefile
|
||||
^^^^^^^^
|
||||
|
||||
The 'co' target has been removed.
|
||||
The ``co`` target has been removed.
|
||||
|
||||
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::
|
||||
:maxdepth: 2
|
||||
|
||||
8.1.2
|
||||
8.1.1
|
||||
8.1.0
|
||||
8.0.1
|
||||
8.0.0
|
||||
|
||||
@ -353,6 +353,7 @@ class BLP1Decoder(_BLPBaseDecoder):
|
||||
data = jpeg_header + data
|
||||
data = BytesIO(data)
|
||||
image = JpegImageFile(data)
|
||||
Image._decompression_bomb_check(image.size)
|
||||
self.tile = image.tile # :/
|
||||
self.fd = image.fp
|
||||
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":
|
||||
fobj.seek(start)
|
||||
im = PngImagePlugin.PngImageFile(fobj)
|
||||
Image._decompression_bomb_check(im.size)
|
||||
return {"RGBA": im}
|
||||
elif (
|
||||
sig[:4] == b"\xff\x4f\xff\x51"
|
||||
@ -121,6 +122,7 @@ def read_png_or_jpeg2000(fobj, start_length, size):
|
||||
jp2kstream = fobj.read(length)
|
||||
f = io.BytesIO(jp2kstream)
|
||||
im = Jpeg2KImagePlugin.Jpeg2KImageFile(f)
|
||||
Image._decompression_bomb_check(im.size)
|
||||
if im.mode != "RGBA":
|
||||
im = im.convert("RGBA")
|
||||
return {"RGBA": im}
|
||||
|
||||
@ -178,6 +178,7 @@ class IcoFile:
|
||||
if data[:8] == PngImagePlugin._MAGIC:
|
||||
# png frame
|
||||
im = PngImagePlugin.PngImageFile(self.buf)
|
||||
Image._decompression_bomb_check(im.size)
|
||||
else:
|
||||
# XOR + AND mask bmp frame
|
||||
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_optional = 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 = whitespace_optional + newline_only + whitespace_optional
|
||||
newline = whitespace_optional_no_nl + newline_only + whitespace_optional_no_nl
|
||||
re_trailer_end = re.compile(
|
||||
whitespace_mandatory
|
||||
+ br"trailer"
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
# Master version for Pillow
|
||||
__version__ = "8.1.0"
|
||||
__version__ = "8.1.2"
|
||||
|
||||
@ -4172,26 +4172,33 @@ setup_module(PyObject* m) {
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *have_libjpegturbo;
|
||||
#ifdef LIBJPEG_TURBO_VERSION
|
||||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_True);
|
||||
#define tostr1(a) #a
|
||||
#define tostr(a) tostr1(a)
|
||||
PyDict_SetItemString(d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
|
||||
#undef tostr
|
||||
#undef tostr1
|
||||
have_libjpegturbo = Py_True;
|
||||
#define tostr1(a) #a
|
||||
#define tostr(a) tostr1(a)
|
||||
PyDict_SetItemString(
|
||||
d, "libjpeg_turbo_version", PyUnicode_FromString(tostr(LIBJPEG_TURBO_VERSION)));
|
||||
#undef tostr
|
||||
#undef tostr1
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", Py_False);
|
||||
have_libjpegturbo = Py_False;
|
||||
#endif
|
||||
Py_INCREF(have_libjpegturbo);
|
||||
PyModule_AddObject(m, "HAVE_LIBJPEGTURBO", have_libjpegturbo);
|
||||
|
||||
PyObject *have_libimagequant;
|
||||
#ifdef HAVE_LIBIMAGEQUANT
|
||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_True);
|
||||
have_libimagequant = Py_True;
|
||||
{
|
||||
extern const char* ImagingImageQuantVersion(void);
|
||||
PyDict_SetItemString(d, "imagequant_version", PyUnicode_FromString(ImagingImageQuantVersion()));
|
||||
}
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", Py_False);
|
||||
have_libimagequant = Py_False;
|
||||
#endif
|
||||
Py_INCREF(have_libimagequant);
|
||||
PyModule_AddObject(m, "HAVE_LIBIMAGEQUANT", have_libimagequant);
|
||||
|
||||
#ifdef HAVE_LIBZ
|
||||
/* zip encoding strategies */
|
||||
@ -4222,11 +4229,14 @@ setup_module(PyObject* m) {
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *have_xcb;
|
||||
#ifdef HAVE_XCB
|
||||
PyModule_AddObject(m, "HAVE_XCB", Py_True);
|
||||
have_xcb = Py_True;
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_XCB", Py_False);
|
||||
have_xcb = Py_False;
|
||||
#endif
|
||||
Py_INCREF(have_xcb);
|
||||
PyModule_AddObject(m, "HAVE_XCB", have_xcb);
|
||||
|
||||
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) {
|
||||
PyObject *have_webpmux;
|
||||
#ifdef HAVE_WEBPMUX
|
||||
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_True);
|
||||
have_webpmux = Py_True;
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_WEBPMUX", Py_False);
|
||||
have_webpmux = Py_False;
|
||||
#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
|
||||
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_True);
|
||||
have_webpanim = Py_True;
|
||||
#else
|
||||
PyModule_AddObject(m, "HAVE_WEBPANIM", Py_False);
|
||||
have_webpanim = Py_False;
|
||||
#endif
|
||||
Py_INCREF(have_webpanim);
|
||||
PyModule_AddObject(m, "HAVE_WEBPANIM", have_webpanim);
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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;
|
||||
int x = 0;
|
||||
|
||||
for (;n > 0; n--)
|
||||
{
|
||||
if (src > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
pixel = *src++;
|
||||
if (n == 1 && pixel != 0) {
|
||||
return n;
|
||||
@ -45,6 +91,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
||||
}
|
||||
x += count;
|
||||
if (pixel & RLE_COPY_FLAG) {
|
||||
if (src + count > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
while(count--) {
|
||||
*dest = *src++;
|
||||
dest += z;
|
||||
@ -52,6 +101,9 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
||||
|
||||
}
|
||||
else {
|
||||
if (src > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
pixel = *src++;
|
||||
while (count--) {
|
||||
*dest = pixel;
|
||||
@ -63,14 +115,16 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z, int xsize)
|
||||
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;
|
||||
|
||||
int x = 0;
|
||||
|
||||
for (;n > 0; n--)
|
||||
{
|
||||
if (src + 1 > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
pixel = src[1];
|
||||
src+=2;
|
||||
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;
|
||||
if (pixel & RLE_COPY_FLAG) {
|
||||
if (src + 2 * count > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
while(count--) {
|
||||
memcpy(dest, src, 2);
|
||||
src += 2;
|
||||
@ -92,6 +149,9 @@ static int expandrow2(UINT8* dest, const UINT8* src, int n, int z, int xsize)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (src + 2 > end_of_buffer) {
|
||||
return -1;
|
||||
}
|
||||
while (count--) {
|
||||
memcpy(dest, src, 2);
|
||||
dest += z * 2;
|
||||
@ -141,7 +201,10 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
return -1;
|
||||
}
|
||||
_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 */
|
||||
@ -175,8 +238,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
read4B(&c->lengthtab[c->tabindex], &ptr[c->bufindex]);
|
||||
}
|
||||
|
||||
state->count += c->tablen * sizeof(UINT32) * 2;
|
||||
|
||||
/* read compressed rows */
|
||||
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->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;
|
||||
goto sgi_finish_decode;
|
||||
}
|
||||
|
||||
c->rleoffset -= SGI_HEADER_SIZE;
|
||||
|
||||
/* row decompression */
|
||||
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 {
|
||||
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) {
|
||||
state->errcode = IMAGING_CODEC_OVERRUN;
|
||||
@ -205,7 +268,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
goto sgi_finish_decode;
|
||||
}
|
||||
|
||||
state->count += c->rlelength;
|
||||
}
|
||||
|
||||
/* store decompressed data in image */
|
||||
@ -213,8 +275,6 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||
|
||||
}
|
||||
|
||||
c->bufsize++;
|
||||
|
||||
sgi_finish_decode: ;
|
||||
|
||||
free(c->starttab);
|
||||
@ -224,5 +284,5 @@ sgi_finish_decode: ;
|
||||
state->errcode=err;
|
||||
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));
|
||||
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);
|
||||
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;
|
||||
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 ));
|
||||
state->errcode = IMAGING_CODEC_BROKEN;
|
||||
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 (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) {
|
||||
/* To avoid dealing with YCbCr subsampling, let libtiff handle it */
|
||||
if (!TIFFReadRGBATile(tiff, x, y, (UINT32 *)state->buffer)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user