Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:chajain
python-Pillow
023-CVE-2021-28678.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 023-CVE-2021-28678.patch of Package python-Pillow
From 496245aa4365d0827390bd0b6fbd11287453b3a1 Mon Sep 17 00:00:00 2001 From: Eric Soroos <eric-github@soroos.net> Date: Sun, 7 Mar 2021 19:00:17 +0100 Subject: [PATCH] Fix BLP DOS -- CVE-2021-28678 * BlpImagePlugin did not properly check that reads after jumping to file offsets returned data. This could lead to a DOS where the decoder could be run a large number of times on empty data * This dates to Pillow 5.1.0 --- ...0745d3f534ad6e4128c51d336ea5489182c69d.blp | Bin 0 -> 284 bytes ...c8f86233ea728339c6e586be7af661a09b5b98.blp | Bin 0 -> 187 bytes ...d8b7c8469d59fc9ffff6b3a3dc0faeae6ea8ee.blp | Bin 0 -> 148 bytes ...73b430977660cdd48d96f6406ddfd4114e69c7.blp | Bin 0 -> 1335 bytes ...a4f2e026b5786529370e5dfe9a11b1bf991f07.blp | Bin 0 -> 571 bytes ...ec061c4afdef39d3edf6da8927240bb07fe9b7.blp | Bin 0 -> 1539 bytes ...9112a065e7183fa7faa2e18929b03e44ee16bf.blp | Bin 0 -> 889 bytes Tests/test_file_blp.py | 19 ++++++++ src/PIL/BlpImagePlugin.py | 43 ++++++++++-------- 9 files changed, 42 insertions(+), 20 deletions(-) create mode 100644 Tests/images/timeout-060745d3f534ad6e4128c51d336ea5489182c69d.blp create mode 100644 Tests/images/timeout-31c8f86233ea728339c6e586be7af661a09b5b98.blp create mode 100644 Tests/images/timeout-60d8b7c8469d59fc9ffff6b3a3dc0faeae6ea8ee.blp create mode 100644 Tests/images/timeout-8073b430977660cdd48d96f6406ddfd4114e69c7.blp create mode 100644 Tests/images/timeout-bba4f2e026b5786529370e5dfe9a11b1bf991f07.blp create mode 100644 Tests/images/timeout-d6ec061c4afdef39d3edf6da8927240bb07fe9b7.blp create mode 100644 Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp diff --git a/Tests/test_file_blp.py b/Tests/test_file_blp.py index f21e4edc512..6f66342515e 100644 --- a/Tests/test_file_blp.py +++ b/Tests/test_file_blp.py @@ -19,7 +19,23 @@ def test_load_blp2_dxt1(): im = Image.open("Tests/images/blp/blp2_dxt1a.blp") target = Image.open("Tests/images/blp/blp2_dxt1a.png") self.assert_image_equal(im, target) + + def test_crashes(self): + test_files = [ + "Tests/images/timeout-060745d3f534ad6e4128c51d336ea5489182c69d.blp", + "Tests/images/timeout-31c8f86233ea728339c6e586be7af661a09b5b98.blp", + "Tests/images/timeout-60d8b7c8469d59fc9ffff6b3a3dc0faeae6ea8ee.blp", + "Tests/images/timeout-8073b430977660cdd48d96f6406ddfd4114e69c7.blp", + "Tests/images/timeout-bba4f2e026b5786529370e5dfe9a11b1bf991f07.blp", + "Tests/images/timeout-d6ec061c4afdef39d3edf6da8927240bb07fe9b7.blp", + "Tests/images/timeout-ef9112a065e7183fa7faa2e18929b03e44ee16bf.blp", + ] + for test_file in test_files: + with open(test_file, "rb") as f: + with Image.open(f) as im: + with self.assertRaises(OSError): + im.load() if __name__ == "__main__": unittest.main() diff --git a/src/PIL/BlpImagePlugin.py b/src/PIL/BlpImagePlugin.py index 88aae80eb96..e07474621d9 100644 --- a/src/PIL/BlpImagePlugin.py +++ b/src/PIL/BlpImagePlugin.py @@ -294,33 +294,36 @@ def decode(self, buffer): raise IOError("Truncated Blp file") return 0, 0 + def _safe_read(self, length): + return ImageFile._safe_read(self.fd, length) + def _read_palette(self): ret = [] for i in range(256): try: - b, g, r, a = struct.unpack("<4B", self.fd.read(4)) + b, g, r, a = struct.unpack("<4B", self._safe_read(4)) except struct.error: break ret.append((b, g, r, a)) return ret def _read_blp_header(self): - self._blp_compression, = struct.unpack("<i", self.fd.read(4)) + self._blp_compression, = struct.unpack("<i", self._safe_read(4)) - self._blp_encoding, = 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_mips, = struct.unpack("<b", self.fd.read(1)) + self._blp_encoding, = struct.unpack("<b", self._safe_read(1)) + self._blp_alpha_depth, = struct.unpack("<b", self._safe_read(1)) + self._blp_alpha_encoding, = struct.unpack("<b", self._safe_read(1)) + self._blp_mips, = struct.unpack("<b", self._safe_read(1)) - self.size = struct.unpack("<II", self.fd.read(8)) + self.size = struct.unpack("<II", self._safe_read(8)) if self.magic == b"BLP1": # Only present for BLP1 - self._blp_encoding, = struct.unpack("<i", self.fd.read(4)) - self._blp_subtype, = struct.unpack("<i", self.fd.read(4)) + self._blp_encoding, = struct.unpack("<i", self._safe_read(4)) + self._blp_subtype, = struct.unpack("<i", self._safe_read(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_offsets = struct.unpack("<16I", self._safe_read(16 * 4)) + self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4)) class BLP1Decoder(_BLPBaseDecoder): @@ -333,7 +336,7 @@ def _load(self): if self._blp_encoding in (4, 5): data = bytearray() palette = self._read_palette() - _data = BytesIO(self.fd.read(self._blp_lengths[0])) + _data = BytesIO(self._safe_read(self._blp_lengths[0])) while True: try: offset, = struct.unpack("<B", _data.read(1)) @@ -355,10 +358,10 @@ def _load(self): def _decode_jpeg_stream(self): from PIL.JpegImagePlugin import JpegImageFile - jpeg_header_size, = struct.unpack("<I", self.fd.read(4)) - jpeg_header = self.fd.read(jpeg_header_size) - self.fd.read(self._blp_offsets[0] - self.fd.tell()) # What IS this? - data = self.fd.read(self._blp_lengths[0]) + jpeg_header_size, = struct.unpack("<I", self._safe_read(4)) + jpeg_header = self._safe_read(jpeg_header_size) + self._safe_read(self._blp_offsets[0] - self.fd.tell()) # What IS this? + data = self._safe_read(self._blp_lengths[0]) data = jpeg_header + data data = BytesIO(data) image = JpegImageFile(data) @@ -380,7 +383,7 @@ def _load(self): # Uncompressed or DirectX compression if self._blp_encoding == BLP_ENCODING_UNCOMPRESSED: - _data = BytesIO(self.fd.read(self._blp_lengths[0])) + _data = BytesIO(self._safe_read(self._blp_lengths[0])) while True: try: offset, = struct.unpack("<B", _data.read(1)) @@ -394,21 +397,21 @@ def _load(self): linesize = (self.size[0] + 3) // 4 * 8 for yb in range((self.size[1] + 3) // 4): for d in decode_dxt1( - self.fd.read(linesize), + self._safe_read(linesize), alpha=bool(self._blp_alpha_depth) ): data += d elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT3: linesize = (self.size[0] + 3) // 4 * 16 for yb in range((self.size[1] + 3) // 4): - for d in decode_dxt3(self.fd.read(linesize)): + for d in decode_dxt3(self._safe_read(linesize)): data += d elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT5: linesize = (self.size[0] + 3) // 4 * 16 for yb in range((self.size[1] + 3) // 4): - for d in decode_dxt5(self.fd.read(linesize)): + for d in decode_dxt5(self._safe_read(linesize)): data += d else: raise BLPFormatError("Unsupported alpha encoding %r" % (
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor