diff --git a/.github/generate-sbom.py b/.github/generate-sbom.py index 3b15a7d918e..e0324d1429e 100755 --- a/.github/generate-sbom.py +++ b/.github/generate-sbom.py @@ -356,6 +356,45 @@ def generate(version: str) -> dict: "scope": "optional", "description": "TIFF codec (optional).", "licenses": [{"license": {"id": "libtiff"}}], + "pedigree": { + "ancestors": [ + { + "bom-ref": "pkg:generic/libtiff@4.7.1#upstream", + "type": "library", + "name": "libtiff", + "version": "4.7.1", + "purl": "pkg:generic/libtiff@4.7.1", + "externalReferences": [ + { + "type": "distribution", + "url": "https://gitlab.com/libtiff/libtiff/-/tags/v4.7.1", + } + ], + } + ], + "patches": [ + { + "type": "cherry-pick", + "diff": { + "text": { + # apply https://gitlab.com/libtiff/libtiff/-/commit/782a11d6 + "content": base64.b64encode( + ( + Path(__file__).parent.parent + / "patches" + / "tiff-4.7.1.tar.gz.patch" + ).read_bytes() + ).decode(), + "encoding": "base64", + } + }, + }, + ], + "notes": ( + "Vendored from upstream libtiff v4.7.1 with a commit from master " + "cherry-picked to fix CVE-2026-4775." + ), + }, "externalReferences": [ {"type": "website", "url": "https://libtiff.gitlab.io/libtiff/"}, { diff --git a/.github/workflows/wheels-dependencies.sh b/.github/workflows/wheels-dependencies.sh index 12593b3f564..8f47b3dea6a 100755 --- a/.github/workflows/wheels-dependencies.sh +++ b/.github/workflows/wheels-dependencies.sh @@ -19,6 +19,7 @@ function check_cibw_archs { # potential cross-build platforms before native platforms to ensure that we pick # up the cross environment. PROJECTDIR=$(pwd) +PATCH_DIR=$(pwd)/patches if [[ "$CIBW_PLATFORM" == "ios" ]]; then check_cibw_archs # On iOS, CIBW_ARCHS is actually a multi-arch - arm64_iphoneos, diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5ee040297fb..3ce0922535f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: rev: v1.5.6 hooks: - id: remove-tabs - exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$) + exclude: (Makefile$|\.bat$|\.cmake$|\.eps$|\.fits$|\.gd$|\.opt$|\.patch$) - repo: https://github.com/pre-commit/mirrors-clang-format rev: v22.1.4 @@ -47,11 +47,11 @@ repos: - id: check-yaml args: [--allow-multiple-documents] - id: end-of-file-fixer - exclude: ^Tests/images/ + exclude: ^Tests/images/|\.patch$ - id: file-contents-sorter files: .github/workflows/Brewfile - id: trailing-whitespace - exclude: ^\.github/.*TEMPLATE|^Tests/(fonts|images)/ + exclude: ^\.github/.*TEMPLATE|^Tests/(fonts|images)/|\.patch$ - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.37.2 diff --git a/MANIFEST.in b/MANIFEST.in index d4623a4a8e5..6623f227d60 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -15,6 +15,7 @@ include tox.ini graft Tests graft Tests/images graft checks +graft patches graft src graft depends graft winbuild diff --git a/patches/README.md b/patches/README.md new file mode 100644 index 00000000000..ff4a8f0994f --- /dev/null +++ b/patches/README.md @@ -0,0 +1,14 @@ +Although we try to use official sources for dependencies, sometimes the official +sources don't support a platform (especially mobile platforms), or there's a bug +fix/feature that is required to support Pillow's usage. + +This folder contains patches that must be applied to official sources, organized +by the platforms that need those patches. + +Each patch is against the root of the unpacked official tarball, and is named by +appending `.patch` to the end of the tarball that is to be patched. This +includes the full version number; so if the version is bumped, the patch will +at a minimum require a filename change. + +Wherever possible, these patches should be contributed upstream, in the hope that +future Pillow versions won't need to maintain these patches. diff --git a/patches/tiff-4.7.1.tar.gz.patch b/patches/tiff-4.7.1.tar.gz.patch new file mode 100644 index 00000000000..e7a88cadcbf --- /dev/null +++ b/patches/tiff-4.7.1.tar.gz.patch @@ -0,0 +1,48 @@ +commit 782a11d6b5b61c6dc21e714950a4af5bf89f023c +Author: Even Rouault +Date: Sun Feb 22 23:32:47 2026 +0100 + + TIFFReadRGBAImage(): prevent integer overflow and later heap overflow on images with huge width in YCbCr tile decoding functions + + Fixes https://gitlab.com/libtiff/libtiff/-/issues/787 + +diff --git a/libtiff/tif_getimage.c b/libtiff/tif_getimage.c +index 4543ddda..fa82d091 100644 +--- libtiff/tif_getimage.c ++++ libtiff/tif_getimage.c +@@ -2224,7 +2224,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) + uint32_t *cp1 = cp + w + toskew; + uint32_t *cp2 = cp1 + w + toskew; + uint32_t *cp3 = cp2 + w + toskew; +- int32_t incr = 3 * w + 4 * toskew; ++ const tmsize_t incr = 3 * (tmsize_t)w + 4 * (tmsize_t)toskew; + + (void)y; + /* adjust fromskew */ +@@ -2364,7 +2364,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr44tile) + DECLAREContigPutFunc(putcontig8bitYCbCr42tile) + { + uint32_t *cp1 = cp + w + toskew; +- int32_t incr = 2 * toskew + w; ++ const tmsize_t incr = 2 * (tmsize_t)toskew + w; + + (void)y; + fromskew = (fromskew / 4) * (4 * 2 + 2); +@@ -2522,7 +2522,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr41tile) + DECLAREContigPutFunc(putcontig8bitYCbCr22tile) + { + uint32_t *cp2; +- int32_t incr = 2 * toskew + w; ++ const tmsize_t incr = 2 * (tmsize_t)toskew + w; + (void)y; + fromskew = (fromskew / 2) * (2 * 2 + 2); + cp2 = cp + w + toskew; +@@ -2625,7 +2625,7 @@ DECLAREContigPutFunc(putcontig8bitYCbCr21tile) + DECLAREContigPutFunc(putcontig8bitYCbCr12tile) + { + uint32_t *cp2; +- int32_t incr = 2 * toskew + w; ++ const tmsize_t incr = 2 * (tmsize_t)toskew + w; + (void)y; + fromskew = (fromskew / 1) * (1 * 2 + 2); + cp2 = cp + w + toskew; diff --git a/wheels/multibuild b/wheels/multibuild index 64739327166..4546f4d4820 160000 --- a/wheels/multibuild +++ b/wheels/multibuild @@ -1 +1 @@ -Subproject commit 64739327166fcad1fa41ad9b23fa910fa244c84f +Subproject commit 4546f4d4820ffd0104b872c3b6187260b3e64edc diff --git a/winbuild/build_prepare.py b/winbuild/build_prepare.py index f55c82112ac..b69d1486e0d 100644 --- a/winbuild/build_prepare.py +++ b/winbuild/build_prepare.py @@ -213,6 +213,10 @@ def cmd_msbuild( # link against libwebp.lib "#ifdef WEBP_SUPPORT": '#ifdef WEBP_SUPPORT\n#pragma comment(lib, "libwebp.lib")', # noqa: E501 }, + r"libtiff\tif_getimage.c": { + "int32_t incr = 3 * w + 4 * toskew;": "const tmsize_t incr = 3 * (tmsize_t)w + 4 * (tmsize_t)toskew;", # noqa: E501 + "int32_t incr = 2 * toskew + w;": "const tmsize_t incr = 2 * (tmsize_t)toskew + w;", # noqa: E501 + }, }, "build": [ *cmds_cmake(