From 91a14660b314d54abbf348a72c9b71359330ce1f Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Wed, 4 Oct 2023 00:04:28 -0700 Subject: [PATCH] Require Pillow >= 10.0.1 and drop shims for older versions --- docs/release_notes.rst | 7 +++++++ pyproject.toml | 2 +- src/ocrmypdf/_exec/ghostscript.py | 14 +++----------- src/ocrmypdf/_pipeline.py | 9 +-------- src/ocrmypdf/imageops.py | 10 +--------- tests/test_rotation.py | 9 +-------- 6 files changed, 14 insertions(+), 37 deletions(-) diff --git a/docs/release_notes.rst b/docs/release_notes.rst index 640f0d1c..faf8c29a 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -28,6 +28,13 @@ tagged yet. .. |OCRmyPDF PyPI| image:: https://img.shields.io/pypi/v/ocrmypdf.svg +v15.1.0 +======= + +- We now require Pillow 10.0.1, due a serious security vulnerability in all earlier + versions of that dependency. The vulnerability concerns WebP images and could + be triggered in OCRmyPDF when creating a PDF from a malicious WebP image. + v15.0.2 ======= diff --git a/pyproject.toml b/pyproject.toml index 9fc4241d..e35473fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ readme = "README.md" license = { text = "MPL-2.0" } requires-python = ">=3.9" dependencies = [ - "Pillow>=9.0.1", + "Pillow>=10.0.1", "deprecation>=2.1.0", "img2pdf>=0.4.4", "packaging>=20", diff --git a/src/ocrmypdf/_exec/ghostscript.py b/src/ocrmypdf/_exec/ghostscript.py index c638c130..92b73a0a 100644 --- a/src/ocrmypdf/_exec/ghostscript.py +++ b/src/ocrmypdf/_exec/ghostscript.py @@ -20,14 +20,6 @@ from ocrmypdf.exceptions import SubprocessOutputError from ocrmypdf.helpers import Resolution from ocrmypdf.subprocess import get_version, run, run_polling_stderr -# Remove this workaround when we require Pillow >= 10 -try: - Transpose = Image.Transpose # type: ignore -except AttributeError: - # Pillow 9 shim - Transpose = Image # type: ignore - - COLOR_CONVERSION_STRATEGIES = frozenset( [ 'CMYK', @@ -137,11 +129,11 @@ def rasterize_pdf( # rotation is a clockwise angle and Image.ROTATE_* is # counterclockwise so this cancels out the rotation if rotation == 90: - im = im.transpose(Transpose.ROTATE_90) + im = im.transpose(Image.Transpose.ROTATE_90) elif rotation == 180: - im = im.transpose(Transpose.ROTATE_180) + im = im.transpose(Image.Transpose.ROTATE_180) elif rotation == 270: - im = im.transpose(Transpose.ROTATE_270) + im = im.transpose(Image.Transpose.ROTATE_270) if rotation % 180 == 90: page_dpi = page_dpi.flip_axis() im.save(fspath(output_file), dpi=page_dpi) diff --git a/src/ocrmypdf/_pipeline.py b/src/ocrmypdf/_pipeline.py index 47cd1533..8c00eae9 100644 --- a/src/ocrmypdf/_pipeline.py +++ b/src/ocrmypdf/_pipeline.py @@ -41,13 +41,6 @@ from ocrmypdf.pdfa import generate_pdfa_ps from ocrmypdf.pdfinfo import Colorspace, Encoding, PageInfo, PdfInfo from ocrmypdf.pluginspec import OrientationConfidence -# Remove this workaround when we require Pillow >= 10 -try: - BICUBIC = Image.Resampling.BICUBIC # type: ignore -except AttributeError: # pragma: no cover - # Pillow 9 shim - BICUBIC = Image.BICUBIC # type: ignore - log = logging.getLogger(__name__) VECTOR_PAGE_DPI = 400 @@ -563,7 +556,7 @@ def preprocess_deskew(input_file: Path, page_context: PageContext) -> Path: # resampling if image is mode '1' or 'P' deskewed = im.rotate( deskew_angle_degrees, - resample=BICUBIC, + resample=Image.Resampling.BICUBIC, fillcolor=ImageColor.getcolor('white', mode=im.mode), # type: ignore ) deskewed.save(output_file, dpi=dpi) diff --git a/src/ocrmypdf/imageops.py b/src/ocrmypdf/imageops.py index fd23202c..adc0d690 100644 --- a/src/ocrmypdf/imageops.py +++ b/src/ocrmypdf/imageops.py @@ -11,14 +11,6 @@ from typing import Optional from PIL import Image -# Remove this workaround when we require Pillow >= 9.1.0 -try: - Resampling = Image.Resampling # type: ignore -except AttributeError: - # Pillow 9 shim - Resampling = Image # type: ignore - - # While from __future__ import annotations, we use singledispatch here, which # does not support annotations. Disable check about using old-style typing # until Python 3.10, OR when drop singledispatch in ocrmypdf 15. @@ -135,7 +127,7 @@ def downsample_image( image: Image.Image, new_size: tuple[int, int], *, - resample_mode: Image.Resampling = Resampling.BICUBIC, + resample_mode: Image.Resampling = Image.Resampling.BICUBIC, reducing_gap: int = 3, ) -> Image.Image: """Downsample an image to fit within the given limits. diff --git a/tests/test_rotation.py b/tests/test_rotation.py index 2fc9ba0c..523cc848 100644 --- a/tests/test_rotation.py +++ b/tests/test_rotation.py @@ -23,13 +23,6 @@ from .conftest import check_ocrmypdf, run_ocrmypdf # pylintx: disable=unused-variable -# Remove this workaround when we require Pillow >= 10 -try: - Transpose = Image.Transpose # type: ignore -except AttributeError: - # Pillow 9 shim - Transpose = Image # type: ignore - RENDERERS = ['hocr', 'sandwich'] @@ -226,7 +219,7 @@ def test_rotate_page_level(image_angle, page_angle, resources, outdir): with Image.open(fspath(resources / 'typewriter.png')) as im: if image_angle != 0: ccw_angle = -image_angle % 360 - im = im.transpose(getattr(Transpose, f'ROTATE_{ccw_angle}')) + im = im.transpose(getattr(Image.Transpose, f'ROTATE_{ccw_angle}')) im.save(memimg, format='PNG') memimg.seek(0) mempdf = BytesIO()