diff --git a/3rdparty/libtiff/CMakeLists.txt b/3rdparty/libtiff/CMakeLists.txt index 9173e207f7..b872ec4f48 100644 --- a/3rdparty/libtiff/CMakeLists.txt +++ b/3rdparty/libtiff/CMakeLists.txt @@ -358,7 +358,7 @@ if(LIBLZMA_LIBRARIES) endif() set(LIBTIFF_MAJOR_VERSION "4") -set(LIBTIFF_MINOR_VERSION "6") +set(LIBTIFF_MINOR_VERSION "7") set(LIBTIFF_MICRO_VERSION "0") set(LIBTIFF_VERSION "${LIBTIFF_MAJOR_VERSION}.${LIBTIFF_MINOR_VERSION}.${LIBTIFF_MICRO_VERSION}") file(READ "RELEASE-DATE" LIBTIFF_RELEASE_DATE content) diff --git a/3rdparty/libtiff/ChangeLog b/3rdparty/libtiff/ChangeLog index 87b5f126bb..a6ab18783c 100644 --- a/3rdparty/libtiff/ChangeLog +++ b/3rdparty/libtiff/ChangeLog @@ -1,3 +1,1586 @@ +2024-09-11 Even Rouault + + libtiff v4.7.0rc2 preparation + +2024-09-11 Even Rouault + + configure.ac: make a provision to look for up to python 3.16 ... + hopefully we'll have ditched autoconf support at that point... + + Fix test dependency on tiff2rgba-32BPP that breaks 'make check -jX' + + test/tiff2ps*.sh scripts: try to use POSIX only diff flags. + +2024-09-11 Even Rouault + + Merge branch 'automake_doc_fix' into 'master' + doc/Makefile.am: make sure that 'doc-html' and 'doc-man' targets have dependencies to avoid them to be rebuilt by successive make + + See merge request libtiff/libtiff!657 + +2024-09-10 Even Rouault + + Merge branch '4_7_0_rst_rgb2ycbcr_thumbnail' into 'master' + v4.7.0.rst: clarify that rgb2ycbcr and thumbnail are not installed + + See merge request libtiff/libtiff!659 + +2024-09-10 Even Rouault + + v4.7.0.rst: clarify that rgb2ycbcr and thumbnail are not installed. + +2024-09-08 Even Rouault + + doc/Makefile.am: make sure that 'doc-html' and 'doc-man' targets have dependencies to avoid them to be rebuilt by successive make + + doc/Makefile.am: move rst_sources and EXTRA_DIST variables on top of file + +2024-09-07 Even Rouault + + Merge branch 'index_rst_formatting_issue' into 'master' + index.rst: fix formatting issue + + See merge request libtiff/libtiff!656 + +2024-09-07 Even Rouault + + index.rst: fix formatting issue. + +2024-09-07 Even Rouault + + Merge branch 'prepare_release_4_7_0' into 'master' + Prepare release 4.7.0 + + See merge request libtiff/libtiff!654 + +2024-09-07 Even Rouault + + Doc: remove 'Master' terminlogy. + + v4.7.0.rst: remove mention about autoconf-archive since that change has been reverted + + Revert "autotools: allow pulling in updated macros from autoconf-archive" + This reverts commit c820d16c30c27b3be6c3d10834b6d75607ae9d77. + + Revert "HOWTO-RELEASE: document the necessary dependencies for producing dist tarballs" + This reverts commit f1a91e42b3f23641cb5559fb60e1d73d201275eb. + + Revert "configure.ac: fix HAVE_OPENGL determination due to recent changes" + This reverts commit c370e67f7fd9320674544113218b7fbca4f65c2b. + + configure.ac: fix HAVE_OPENGL determination due to recent changes. + + Update version numbers for 4.7.0. + + Update ChangeLog and create release notes for v4.7.0. + +2024-09-06 Even Rouault + + typo fixes. + +2024-09-06 Even Rouault + + Merge branch 'autoconf-archive' into 'master' + autotools: allow pulling in updated macros from autoconf-archive + + See merge request libtiff/libtiff!645 + +2024-09-06 Even Rouault + + Merge branch 'remove_last_usage_of_get_field_type' into 'master' + Change last usage of get_field_type at TIFFWriteDirectorySec() to set_field_type + + See merge request libtiff/libtiff!653 + +2024-09-06 Even Rouault + + libtiff v4.7.0rc1 preparation + +2024-09-06 Even Rouault + + Merge branch 'autoconf-archive' into 'master' + autotools: allow pulling in updated macros from autoconf-archive + + See merge request libtiff/libtiff!645 + +2024-09-06 Even Rouault + + Merge branch 'remove_last_usage_of_get_field_type' into 'master' + Change last usage of get_field_type at TIFFWriteDirectorySec() to set_field_type + + See merge request libtiff/libtiff!653 + +2024-09-05 Su_Laus + + Change last usage of get_field_type at TIFFWriteDirectorySec() for codec related tags to set_field_type. + +2024-09-03 Eli Schwartz + + HOWTO-RELEASE: document the necessary dependencies for producing dist tarballs + + autogen.sh: actually return failure if any step failed. + Previously, it exited with failure if and only if the wget calls failed. + But it is possible for any command to fail, e.g. if the autotools are + broken, misconfigured, or missing dependencies. + +2024-09-03 Eli Schwartz + + autotools: allow pulling in updated macros from autoconf-archive. + Instead of inlining a few macros in acinclude.m4 and forgetting about + them, teach aclocal to install the macros to m4/ when autoreconf is run. + They are no longer tracked in one big file, nor tracked at all in git, + but producing dist tarballs will bundle them up just like `configure` + and `Makefile.in`. + + Note: previous behavior of AX_CHECK_GL* was to simply ignore support and + proceed, if it was asked for and not found. The updated macros expect to + opt into this by specifying action-if-not-found. + + VL_* is obsolete. Upgrade to AX_CFLAGS_WARN_ALL. + +2024-09-03 Even Rouault + + Merge branch 'XZY2RGB' into 'master' + Fixes #644 Index comparison as size_t to avoid overflow in TIFFXYZToRGB + + Closes #644 + + See merge request libtiff/libtiff!649 + +2024-09-03 Nicolas Badoux + + Fixes #644 Index comparison as size_t to avoid overflow in TIFFXYZToRGB. + +2024-09-01 Even Rouault + + Merge branch 'ci_werror' into 'master' + CI: build with -Wall -Wextra -Werror + + See merge request libtiff/libtiff!652 + +2024-08-30 Even Rouault + + configure.ac: avoid -Werror passed to CFLAGS to interfere with feature detection + + CI: build with -Wall -Wextra -Werror. + +2024-08-30 Roger Leigh + + Merge branch 'ci-old-update' into 'master' + ci: Update "old" build jobs to use Ubuntu 22.04 + + See merge request libtiff/libtiff!651 + +2024-08-30 Roger Leigh + + ci: Update "old" build jobs to use Ubuntu 22.04. + +2024-08-30 Even Rouault + + Merge branch 'ci-ubuntu-22.04' into 'master' + ci: Update to use Ubuntu 24.04 CI images + + See merge request libtiff/libtiff!650 + +2024-08-30 Roger Leigh + + ci: Update to use Ubuntu 24.04 CI images. + +2024-08-28 Even Rouault + + Merge branch 'uv_encode' into 'master' + Fix #645 by using unsigned int for variable indexing an array in uv_decode() and uv_encode() + + Closes #645 + + See merge request libtiff/libtiff!648 + +2024-08-28 Nicolas Badoux + + Fix #645 by using unsigned int for variable indexing an array in uv_decode() and uv_encode() + Change `vi` to unsigned int in `uv_decode()` and `uv_encode()` to ensure that upper bound `UV_NVS` cannot be satisfied by a negative value which will overflow when cast to an unsigned value at array access time. This fixes issue #645 where a segmentation fault was caused. + +2024-08-27 Even Rouault + + Merge branch 'fix_643_solitary_CustomDirectory_read' into 'master' + Fix #643 by initializing pointer to TIFFSetField() and TIFFGetField() before TIFFReadGPSDirectory + + Closes #643 + + See merge request libtiff/libtiff!647 + +2024-08-27 Su Laus + + Fix #643 by initializing pointer to TIFFSetField() and TIFFGetField() before TIFFReadGPSDirectory + Initialize pointer to TIFFSetField() and TIFFGetField() (i.e. tif-\>tif_tagmethods.vsetfield and tif-\>tif_tagmethods.vgetfield) even if the file is opened with "h" option. This fixes issue #643 where a segmentation fault was caused. + +2024-08-25 Even Rouault + + Merge branch 'tiff_strip' into 'master' + Add non-zero check before division in TIFFComputeStrip + + See merge request libtiff/libtiff!646 + +2024-08-23 Nicolas Badoux + + Add non-zero check before division in TIFFComputeStrip. + +2024-08-15 Even Rouault + + Merge branch 'fix_564' into 'master' + TIFFScanlineSize64(): revert merge request #564 + + See merge request libtiff/libtiff!644 + +2024-08-15 Even Rouault + + TIFFScanlineSize64(): revert merge request #564. + https://gitlab.com/libtiff/libtiff/-/merge_requests/564 broke decoding of: "tools/tiffcp -c none in.tif out.tif" + with [in.tif](/uploads/0475a88cf6e66652b030a0a3a0c47313/in.tif) + leading to shift each line of the target image by one extra pixel at each line. + Unfortunately, this cancels what https://gitlab.com/libtiff/libtiff/-/merge_requests/564 tried to fix. I'll let @caolanm propose an alternative fix in a follow-up merge request + +2024-08-15 Even Rouault + + Merge branch 'coverity_fix_from_MR_634' into 'master' + Fix some Coverity Scan issues introduced by MR 634. + + See merge request libtiff/libtiff!643 + +2024-08-14 Su_Laus + + Fix some Coverity Scan issues introduced by MR 634. + +2024-08-11 Even Rouault + + Merge branch 'lerc-pkgconfig' into 'master' + libtiff-4.pc: Fix `Requires.private` missing `Lerc`. + + See merge request libtiff/libtiff!633 + +2024-08-11 Even Rouault + + Merge branch 'manpage_update_directory_incrementing' into 'master' + Amend manpages for changes in current directory index behaviour. + + See merge request libtiff/libtiff!639 + +2024-08-11 Su Laus + + Amend manpages for changes in current directory index behaviour. + +2024-08-11 Even Rouault + + Merge branch 'tiffcrop_coverity_20240723' into 'master' + Attempt to address tiffcrop Coverity scan issues 1605444, 1605445, and 1605449. + + See merge request libtiff/libtiff!642 + +2024-08-11 Lee Howard + + Attempt to address tiffcrop Coverity scan issues 1605444, 1605445, and 1605449. + +2024-08-11 Even Rouault + + Merge branch 'fix_CurDir_wrong_incrementing' into 'master' + Fix cases where tif_curdir is set incorrectly + + See merge request libtiff/libtiff!634 + +2024-08-11 Su Laus + + Fix cases where tif_curdir is set incorrectly. + Fix cases where the current directory number (tif_curdir) is set inconsistently or incorrectly, depending on the previous history. + + See additional checks and tests in test/test_directory.c of this MR for intended setting of tif_curdir (i.e. TIFFCurrentDirectory(tif)). + +2024-07-12 Even Rouault + + Merge branch 'coverity_fixes_tiff2pdf_#2' into 'master' + Try to fix additional Coverity issues in tiff2pdf + + See merge request libtiff/libtiff!641 + +2024-07-12 Su Laus + + Try to fix additional Coverity issues in tiff2pdf. + +2024-07-10 Even Rouault + + Merge branch 'fix_autoconf_diff_parameter_crlf' into 'master' + Add parameter for "diff" used in autoconf test scripts to ignore LF and CRLF differences. + + See merge request libtiff/libtiff!640 + +2024-07-09 Even Rouault + + Merge branch 'coverity_fixes_tiff2pdf' into 'master' + Fix Coverity issues in tiff2pdf. + + See merge request libtiff/libtiff!638 + +2024-07-09 Su Laus + + Fix Coverity issues in tiff2pdf. + +2024-06-29 Su_Laus + + Add parameter for "diff" used in autoconf test scripts to ignore LF and CRLF differences. + +2024-06-28 Even Rouault + + Merge branch 'coverity_fixes_test_thumbnail' into 'master' + Coverity Scan fixes in thumbnail.c and custom_dir_EXIF_231.c + + See merge request libtiff/libtiff!637 + +2024-06-28 Su Laus + + Coverity Scan fixes in thumbnail.c and custom_dir_EXIF_231.c. + +2024-06-25 Even Rouault + + Merge branch 'coverity_fixes' into 'master' + Try to silence new Coverity Scan false positives + + See merge request libtiff/libtiff!636 + +2024-06-24 Even Rouault + + Try to silence new Coverity Scan false positives. + There are other warnings in tools/ that I'll let others deal with. + +2024-06-24 Even Rouault + + Merge branch 'fix/make' into 'master' + fix: error when running make clean + + Closes #630 + + See merge request libtiff/libtiff!635 + +2024-06-24 Kévin Dunglas + + fix: error when running make clean. + +2024-06-15 Niklas Hambüchen + + libtiff-4.pc: Fix `Requires.private` missing `Lerc`. + It provides a `.pc` file starting from version 4 in: + + https://github.com/Esri/lerc/blob/8d6e8251544bbe1379feb0fe0a0934e43ca1a6cd/Lerc.pc.in + + libtiff's CMake build system already has support for this, + adding `Lerc` to `Requires.private` if Lerc is >= 4. + + In contrast to the CMake build system, autoconf has no good way + to check for checking the Lerc version, we do it unconditionally + there. + +2024-06-13 Even Rouault + + Merge branch 'rfc02_text__restore_tools' into 'master' + Text for RFC 2: Restoring needed libtiff tools + + See merge request libtiff/libtiff!581 + +2024-06-13 Even Rouault + + Merge branch 'add_some_conversion_test_to_cmake' into 'master' + Port some basic sanity checks from autoconf to cmake. + + See merge request libtiff/libtiff!630 + +2024-06-10 Even Rouault + + Merge branch 'tiffcp_coverity_check_malloc_return' into 'master' + tiffcp: Add check for limitMalloc return to fix Coverity CID 1603334 + + See merge request libtiff/libtiff!632 + +2024-06-10 Su_Laus + + tiffcp add check for limitMalloc return to fix Coverity CID 1603334. + +2024-06-07 Even Rouault + + Merge branch 'aim-nara-master-patch-67955' into 'master' + Remove unnecessary `2` in tiffcmp name + + See merge request libtiff/libtiff!631 + +2024-06-07 AIM | Nara + + Remove unnecessary `2` in tiffcmp name. + +2024-05-30 Su_Laus + + Port some basic sanity checks from autoconf to cmake. Checks are for tiffcp and tiffcrop RGB->YCbCr JPEG conversions (see MR !611 / 'tiffcp_tiffcrop_RGB_YCbCr_tests') + +2024-05-29 Even Rouault + + Merge branch 'ofz65182' into 'master' + an issue seen in putcontig8bitYCbCr22tile + + See merge request libtiff/libtiff!564 + +2024-05-29 Caolán McNamara + + TIFFScanlineSize64(): fix computation in non-JPEG YCbCr case (#564) + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=65182 + +2024-05-29 Even Rouault + + Merge branch 'fix_375' into 'master' + TIFFRead[Scanline/EncodedStrip/EncodeTile]: 0-initialize output buffer if setupdecode fails ; most codecs: zero-initialize (not-yet-written parts of) output buffer if failure + + Closes #375 + + See merge request libtiff/libtiff!628 + +2024-05-29 Even Rouault + + Merge branch 'tiff2pdf-planar' into 'master' + Inconsistent PLANARCONFIG value for the input and output TIFF in tiff2pdf.c + + See merge request libtiff/libtiff!629 + +2024-05-29 Timothy Lyanguzov + + Inconsistent PLANARCONFIG value for the input and output TIFF in tiff2pdf.c + Fixed a bug in tiff2pdf.c whereas the PLANARCONFIG for the output TIFF is set to a fixed value of PLANARCONFIG_CONTIG as opposed to match the value of the input TIFF. + This mainly manifest in the heap-buffer-overread due to the difference of sizes in the buffers (between input and output) allocated and read to the size of output buffer. + + Reimplementation of !92 + +2024-05-27 Even Rouault + + tif_lzma/tif_lzw: add code comments. + +2024-05-26 Even Rouault + + ZSTDDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + PixarLogDecode: zero-initialize output buffer if failure. + + PackBitsDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + JPEGDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + LERCDecode: zero-initialize output buffer if failure. + + LZMADecode: zero-initialize (not-yet-written parts of) output buffer if failure, and handle repeated calls to decoding same tile/strip if previous failure occured + + TWebPDecode: zero-initialize output buffer if failure, and handle repeated calls to decoding same tile/strip if previous failure occured + + ThunderDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + OJPEGDecode: zero-initialize output buffer if failure. + + JBIGDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + ZIPDecode: zero-initialize (not-yet-written parts of) output buffer if failure, and handle repeated calls to decoding same tile/strip if previous failure occured + + LZWDecode: zero-initialize (not-yet-written parts of) output buffer if failure + + TIFFRead[Scanline/EncodedStrip/EncodeTile]: 0-initialize output buffer if setupdecode fails + Fixes #375 + +2024-05-25 Su_Laus + + Text for RFC 2: Restoring needed libtiff tools - file added to doc/Makefile.am and rebased. + + Text for RFC 2: Restoring needed libtiff tools - approved with voting history updated. + + Text for RFC 2: Restoring needed libtiff tools - further amended. + + Text for RFC 2: Restoring needed libtiff tools - amended. + + Text for RFC 2: Restoring needed libtiff tools. + +2024-05-23 Even Rouault + + Merge branch 'tiff2pdf_539' into 'master' + fix tiff2pdf issue #539; however, there certainly remain many JPEG-compressed... + + See merge request libtiff/libtiff!597 + +2024-05-23 Lee Howard + + tiff2pdf: fix issue with JPEG restart-interval marker when converting from JPEG-compressed files + Fixes #539 + + however, there certainly remain many JPEG-compressed TIFFs which tiff2pdf will fumble without disabling data passthrough (using the -n option) - I supect that it has to do with the JPEG tables being removed from the JPEG and placed into the TIFF headers - as tiff2pdf would need to put these back into the JPEG instead of just passing the data through to the PDF + +2024-05-22 Even Rouault + + Merge branch 'test_fix' into 'master' + test/Makefile.am: make sure that all test images are bundled by make dist even... + + See merge request libtiff/libtiff!626 + +2024-05-22 Even Rouault + + Merge branch 'add_missing_rst_files' into 'master' + doc/Makefile.am: add rfcs/ files in rst_sources variable + + See merge request libtiff/libtiff!624 + +2024-05-22 Even Rouault + + test/Makefile.am: make sure that all test images are bundled by make dist even if JPEG or JBIG is not available + +2024-05-22 Even Rouault + + Merge branch 'timothyl/32bpp-cmake-test' into 'master' + Add new test to CMake + + See merge request libtiff/libtiff!625 + +2024-05-22 Timothy Lyanguzov + + Add new test to CMake. + See previous merge request libtiff/libtiff!611 + +2024-05-22 Even Rouault + + doc/Makefile.am: add rfcs/ files in rst_sources variable. + +2024-05-22 Even Rouault + + Merge branch 'tiffcp_tiffcrop_RGB_YCbCr_tests' into 'master' + Add some basic sanity checks for tiffcp and tiffcrop RGB->YCbCr JPEG conversions. + + See merge request libtiff/libtiff!611 + +2024-05-22 Lee Howard + + Add some basic sanity checks for tiffcp and tiffcrop RGB->YCbCr JPEG conversions. + +2024-05-21 Even Rouault + + Merge branch 'tiffcp_LZW_JBIG_test' into 'master' + Add basic sanity check for tiffcp LZW->JBIG conversion. + + See merge request libtiff/libtiff!612 + +2024-05-21 Even Rouault + + Merge branch 'tiffcrop_masonwilde_fix' into 'master' + Apply "Fix heap-buffer-overflow in function extractImageSection" + + See merge request libtiff/libtiff!613 + +2024-05-21 Lee Howard + + tiffcrop: Apply "Fix heap-buffer-overflow in function extractImageSection" + https://gitlab.com/masonwilde/libtiff/-/commit/848434a81c443f59ec90d41218eba6e48a450a11 + + authored by zhailiangliang commit 848434a81c443f59ec90d41218eba6e48a450a11 + + The overflow conditions were previously addressed, but this provides additional error messages. + +2024-05-21 Even Rouault + + Merge branch 'fix_183_alternative' into 'master' + OJPEG: reset subsampling_convert_state =0 in OJPEGPreDecode (fixes tiff2pdf issue #183) + + See merge request libtiff/libtiff!621 + +2024-05-21 Even Rouault + + Merge branch 'thunder-fix' into 'master' + A fix for Thunder RLE + + See merge request libtiff/libtiff!623 + +2024-05-21 Timothy Lyanguzov + + A fix for Thunder RLE. + The commit https://gitlab.com/robinwatts/libtiff/-/commit/be0519ca3d222c19008fe160873f3b5c28e6b36b states: + + Thunder RLE can fail to decode last run. Bug seen with GhostPDL. Decode of test tif file gives valgrind errors due to the "thunder decode" failing to extract the final run of compressed pixels. + + The logic in the decoder, presumably intended to spot overruns of data, is incorrect in that runs that end at the end of a row (npixels == maxpixels) will not be decoded. + + Fix this by limiting 'n', the number of pixels to copy. Note that npixels is updated by the 'unlimited' value to ensure the error reporting at the end of the loop still works. + +2024-05-18 Even Rouault + + Merge branch 'tiff2ps_fax2tiff_476' into 'master' + fix fax2ps and fax2tiff bugs #476 + + See merge request libtiff/libtiff!598 + +2024-05-18 Lee Howard + + Fix fax2ps and fax2tiff memory leaks. + Fixes #476 + +2024-05-17 Even Rouault + + Merge branch 'tiff2rgba_469' into 'master' + fix tiff2rgba issue #469 + + See merge request libtiff/libtiff!600 + +2024-05-17 Even Rouault + + Merge branch 'formatting-fixes' into 'master' + Formatting fixes + + See merge request libtiff/libtiff!622 + +2024-05-17 Even Rouault + + Formatting fixes. + +2024-05-17 Even Rouault + + Merge branch 'coverity_fixes' into 'master' + 3 Coverity Scan fixes in tools & contrib + + See merge request libtiff/libtiff!592 + +2024-05-17 Even Rouault + + Merge branch 'tiff2pdf_596' into 'master' + tiff2pdf issue #596 + + See merge request libtiff/libtiff!594 + +2024-05-17 Even Rouault + + Merge branch 'tiffdither_473' into 'master' + fix tiffdither bug #473 + + See merge request libtiff/libtiff!599 + +2024-05-17 Even Rouault + + Merge branch 'fax2tiff_468' into 'master' + fix fax2tiff issue #468 + + See merge request libtiff/libtiff!601 + +2024-05-17 Even Rouault + + Merge branch 'tiff2rgba_background' into 'master' + Add background gradient option for tiff2rgba alpha compositing. + + See merge request libtiff/libtiff!610 + +2024-05-17 Lee Howard + + Add background gradient option for tiff2rgba alpha compositing. + +2024-05-17 Even Rouault + + Merge branch 'tiff2pdf_253' into 'master' + Fix tiff2pdf issue #253 - red and blue were being swapped for RGBA decoding + + See merge request libtiff/libtiff!603 + +2024-05-17 Even Rouault + + Merge branch 'fax2tiff_249' into 'master' + Fix fax2tiff issue #249, unreasonable width input + + See merge request libtiff/libtiff!604 + +2024-05-17 Even Rouault + + Merge branch 'tiffcp_tiffcrop_228' into 'master' + correct tiffcp and tiffcrop issue #228 + + See merge request libtiff/libtiff!605 + +2024-05-17 Even Rouault + + OJPEG: reset subsampling_convert_state =0 in OJPEGPreDecode (fixes tiff2pdf issue #183) + +2024-05-17 Even Rouault + + Merge branch 'fax2tiff_191' into 'master' + Fix fax2tiff issue #191 - EOFB interpretation + + See merge request libtiff/libtiff!606 + +2024-05-17 Even Rouault + + Merge branch 'tiff2pdf_98' into 'master' + Fix tiff2pdf documentation issue #98 + + See merge request libtiff/libtiff!608 + +2024-05-17 Even Rouault + + Merge branch 'tiffgt_warning' into 'master' + Avoids a warning regarding fallthrough. + + See merge request libtiff/libtiff!609 + +2024-05-17 Even Rouault + + Merge branch 'tiffcrop_542_550_552' into 'master' + tiffcrop: fixes #542, #550, #552 (buffer overflows, use after free) + + See merge request libtiff/libtiff!595 + +2024-05-17 Lee Howard + + tiffcrop: fixes #542, #550, #552 (buffer overflows, use after free) + +2024-05-17 Even Rouault + + Merge branch 'Fedora_am_version' into 'master' + libtiff-am-version.patch from Fedora stating: + + See merge request libtiff/libtiff!617 + +2024-05-17 Even Rouault + + Merge branch 'formatting-fixes' into 'master' + Code formatting fixes + + See merge request libtiff/libtiff!620 + +2024-05-17 Even Rouault + + Code formatting fixes. + Result of running ``pre-commit run --all`` + +2024-05-17 Even Rouault + + Merge branch 'sphinx_quotes_dashes' into 'master' + Don't let Sphinx inconsistently alter quotes and dashes in rst files. + + See merge request libtiff/libtiff!615 + +2024-05-17 Even Rouault + + Merge branch 'tiffmedian_599' into 'master' + tiffmedian issue #599 + + See merge request libtiff/libtiff!593 + +2024-05-17 Lee Howard + + tiffmedian: fix memory leaks. + Closes #599 + +2024-05-17 Even Rouault + + Merge branch 'more_spelling_corrections' into 'master' + Typo fixes following... + + See merge request libtiff/libtiff!618 + +2024-05-17 Lee Howard + + Typo fixes following https://gitlab.com/libtiff/libtiff/-/commit/c95c77350820e19c8e273925bc97259727d19695 + +2024-05-16 Lee Howard + + libtiff-am-version.patch from Fedora stating: Back off the minimum required automake version to 1.11. There isn't anything in libtiff currently that actually requires 1.12, and changing this allows the package to be built on pre-F18 machines for easier testing. + + Don't let Sphinx inconsistently alter quotes and dashes in rst files. Author: Laszlo Boszormenyi (GCS) Bug-Debian: https://bugs.debian.org/1028456 + + Add basic sanity check for tiffcp LZW->JBIG conversion. + + Avoids a warning regarding fallthrough. + + Fix tiff2pdf documentation issue #98. + + Fix fax2tiff issue #191 - EOFB interpretation. + + Update tiffcp.c. + + Correct tiffcrop output of RGB JPEG and tiffcp/tiffcrop documentation - issue #228 + + Fix tiffcp and tiffcrop issue 228 - step 1. + + Fix fax2tiff issue #249, unreasonable width input. + + Fix tiff2pdf issue #253 - red and blue were being swapped for RGBA decoding + + fix fax2tiff issue #468. + + fix tiff2rgba issue #469. + + fix tiffdither bug #473. + + tiff2pdf issue #596. + +2024-05-16 Even Rouault + + contrib/addtiffo: validate return of TIFFWriteEncodedXXXX() calls (CID 1024680) + + tiffdump.c: fix wrong printf formattre in error message (CID 1472932) + + tiffset.c: avoid false positive Coverity Scan warning on 64-bit builds (CID 1518997) + +2024-05-16 Even Rouault + + Merge branch 'master' into 'master' + Fix some Coverity warnings. + + See merge request libtiff/libtiff!590 + +2024-05-16 Lee Howard + + Fix some Coverity warnings. + +2024-05-13 Even Rouault + + Merge branch 'revert_tools_removement' into 'master' + Restore tools from archive and unsupported and tiffcp -i option with revert. + + See merge request libtiff/libtiff!589 + +2024-05-11 Su_Laus + + Apply some newer changes to the reverted code and prepare note for 4.7.0. + + Revert "Remove -i option (ignore errors) from tiffcp, because almost all fuzzer issues were consequential errors from ignored errors because of the "-i" option." + This reverts commit 280a568ae887c27a422a5da862398ffdbcd9b84d. + +2024-05-11 Su_Laus + + Revert "Move most TIFF tools to archive and keep some as unsupported (see #580)." + This reverts commit eab89a627f0a65e9a1a47c4b30b4802c80b1ac45. + + # Conflicts: + # tools/unsupported/CMakeLists.txt + # tools/unsupported/tif_tools-unsupported_versioninfo.rc + +2024-05-10 Even Rouault + + Merge branch 'calloc-transposed-args' into 'master' + Fix -Werror=calloc-transposed-args with gcc 14 + + See merge request libtiff/libtiff!588 + +2024-05-10 Even Rouault + + Fix -Werror=calloc-transposed-args with gcc 14. + +2024-05-09 Even Rouault + + Merge branch 'EvaluateIFDdatasizeReading_ossfuzz_68327' into 'master' + EvaluateIFDdatasizeReading(): avoid unsigned integer overflow (master only) + + See merge request libtiff/libtiff!586 + +2024-04-27 Even Rouault + + EvaluateIFDdatasizeReading(): avoid unsigned integer overflow (master only) + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=68327 + +2024-04-25 Even Rouault + + Merge branch 'ci-appveyor-cygwin-upgrade' into 'master' + appveyor: Upgrade cygwin packages + + See merge request libtiff/libtiff!585 + +2024-04-25 Roger Leigh + + appveyor: Upgrade cygwin packages. + +2024-04-25 Even Rouault + + Merge branch 'libjpeg_turbo_3_0' into 'master' + Change messages/comments refering libjpeg-turbo 2.2 to 3.0 + + See merge request libtiff/libtiff!584 + +2024-04-24 Even Rouault + + Change messages/comments refering libjpeg-turbo 2.2 to 3.0. + libjpeg-turbo 2.2 was actually released as 3.0. Reflect that + +2024-04-22 Even Rouault + + Merge branch 'EvaluateIFDdatasizeReading_unsigned_int_overflow_fix' into 'master' + EvaluateIFDdatasizeReading(): avoid potential unsigned integer overflow on corrupted tag + + See merge request libtiff/libtiff!582 + +2024-04-22 Even Rouault + + EvaluateIFDdatasizeReading(): avoid potential unsigned integer overflow on corrupted tag + +2024-04-22 Even Rouault + + Merge branch 'tif_dir_logging-627' into 'master' + tif_dir.c: Log source file, line number, and input tif for directory count error. + + Closes #627 + + See merge request libtiff/libtiff!583 + +2024-04-22 Kurt Schwehr + + tif_dir.c: Log source file, line number, and input tif for directory count error. + +2024-04-14 Even Rouault + + Merge branch 'fix_readrgbastrip_fpe' into 'master' + Avoiding FPEs (division by zero) in tif_getimage.c + + See merge request libtiff/libtiff!580 + +2024-04-09 Zurab Tsinadze + + Avoid FPEs (division by zero) in tif_getimage.c. + +2024-04-06 Even Rouault + + Merge branch 'appveyor-vs2022' into 'master' + appveyor: Add VS2022 builds + + See merge request libtiff/libtiff!579 + +2024-04-06 Roger Leigh + + appveyor: Add VS2022 builds. + +2024-04-04 Roger Leigh + + Merge branch 'appveyor-mingw-fix' into 'master' + appveyor: Use MinGW-w64 + + See merge request libtiff/libtiff!578 + +2024-04-04 Roger Leigh + + appveyor: Use MinGW-w64. + +2024-04-03 Even Rouault + + Merge branch 'update_rfc1_status' into 'master' + RFC1: update status to adopted + + See merge request libtiff/libtiff!577 + +2024-04-03 Even Rouault + + RFC1: update status to adopted. + +2024-04-03 Even Rouault + + Merge branch 'rfc1_psc' into 'master' + Doc: add 'RFC 1: Project Steering Committee Guidelines' and a PSC page + + See merge request libtiff/libtiff!566 + +2024-04-03 Even Rouault + + Doc: add 'RFC 1: Project Steering Committee Guidelines' and a PSC page. + +2024-04-02 Even Rouault + + Merge branch 'fix_coverity_test_directory_expansion' into 'master' + Fix coverity scan issue in test_directory.c + + See merge request libtiff/libtiff!576 + +2024-04-02 Su_Laus + + Fix coverity scan issue in test_directory.c. + +2024-04-02 Even Rouault + + Merge branch 'typo_fixes' into 'master' + Various typo fixes + + See merge request libtiff/libtiff!575 + +2024-04-02 Even Rouault + + Various typo fixes. + +2024-03-31 Even Rouault + + Merge branch 'test_directory_expansion_endianness' into 'master' + Enhance test_directory.c with big-endian and little-endian test cases + + See merge request libtiff/libtiff!574 + +2024-03-30 Su_Laus + + Enhance test/test_directory.c with big-endian and little-endian test cases. + Insert testcase into test_directory.c for #618 "Failure in TIFFSetSubDirectory() will break subsequent TIFFSetDirectory() calls". + +2024-03-29 Even Rouault + + Merge branch 'correct_coverity_issues_from_avoid_IFD_overwriting' into 'master' + Correct some coverity issues from "avoid IFD overwriting" + + See merge request libtiff/libtiff!573 + +2024-03-29 Su_Laus + + Correct some coverity issues from "avoid IFD overwriting". + +2024-03-28 Even Rouault + + Merge branch 'fix_gdal_9548' into 'master' + LERC codec: deal with issues with multi-band PlanarConfig=Contig and NaN values + + See merge request libtiff/libtiff!572 + +2024-03-26 Even Rouault + + Merge branch 'avoid_IFD_overwriting_other_data_TIFFWriteDirectory' into 'master' + TIFFWriteDirectory: Avoid overwriting following data if an IFD is enlarged. + + See merge request libtiff/libtiff!565 + +2024-03-26 Su Laus + + TIFFWriteDirectory: Avoid overwriting following data if an IFD is enlarged. + Avoid overwriting other data if an IFD that has already been written is enlarged. If entries are to be changed in an IFD that has already been written to the file, the memory area can be overwritten as long as the IFD data volume has not increased. Otherwise, the IFD must be written to a different location in the file. Up to now, LibTIFF has simply overwritten the IFD and other data areas in the file. + + With this MR, the size of the IFD, and location of IFD data, is tracked and checked if the IFD can be safely overwritten or has to be re-written to another location. + +2024-03-24 Even Rouault + + LERC codec: deal with issues with multi-band PlanarConfig=Contig and NaN values + Fixes https://github.com/OSGeo/gdal/issues/9530. + Cf https://github.com/OSGeo/gdal/pull/9548 for the GDAL specific fix. + + The LERC codec up-to-now didn't do any special processing when writing a strile + in a multi-band PlanarConfig=Contig file, resulting in corruptions. Now we + generate a mask buffer in that situation. Actually, if the NaN values are not + at the same location accross bands, we need to write one mask-per-band, which + requires liblerc >= 3.0, and in that situation change the LERC blob to + multi-band instead of multi-depth/dim, with liblerc >= 3.0. When all bands have + NaN values at the same location, we generate a single mask, which is compatible + of liblerc < 3.0, but requires at last this version of libtiff to be read. This + is the best solution we come with to fix the issue while having the maximum + backward compatibility. + +2024-03-24 Even Rouault + + Merge branch 'harmonize_TIFFheader_swapping' into 'master' + Correct and harmonize swapping of internal 'tif_header' parameters. + + See merge request libtiff/libtiff!571 + +2024-03-24 Su Laus + + Correct and harmonize swapping of internal 'tif_header' parameters. + +2024-03-19 Even Rouault + + Merge branch 'chore/printf-format-specifiers' into 'master' + chore: use correct format specifiers + + See merge request libtiff/libtiff!570 + +2024-03-19 Tom + + chore: use correct format specifiers. + When building on my Mac, I get the following warnings: + + libtiff/tools/tiffcp.c:154:24: warning: format specifies type 'unsigned short' but the argument has type 'tdir_t' (aka 'unsigned int') [-Wformat] + comma, nextImage); + ^~~~~~~~~ + libtiff/tools/tiffcp.c:1295:39: warning: format specifies type 'unsigned short' but the argument has type 'tdir_t' (aka 'unsigned int') [-Wformat] + TIFFFileName(bias), TIFFCurrentDirectory(bias), + ^~~~~~~~~~~~~~~~~~~~~~~~~~ + libtiff/tools/tiffcp.c:1296:37: warning: format specifies type 'unsigned short' but the argument has type 'tdir_t' (aka 'unsigned int') [-Wformat] + TIFFFileName(in), TIFFCurrentDirectory(in)); + ^~~~~~~~~~~~~~~~~~~~~~~~ + libtiff/tools/tiffcp.c:1303:37: warning: format specifies type 'unsigned short' but the argument has type 'tdir_t' (aka 'unsigned int') [-Wformat] + TIFFFileName(in), TIFFCurrentDirectory(in)); + ^~~~~~~~~~~~~~~~~~~~~~~~ + libtiff/tools/tiffsplit.c:174:21: warning: format specifies type 'long long' but the argument has type 'size_t' (aka 'unsigned long') [-Wformat] + path_len); + ^~~~~~~~ + + This updates the format specifiers from `PRIu16` to `PRIu32` for `tdir_t` + (which is a `typdef`ed `uint32_t`) and from `TIFF_SSIZE_FORMAT` to + `TIFF_SIZE_FORMAT` for `size_t`, which makes sense given that it's an unsigned + type. + +2024-03-16 Even Rouault + + Merge branch 'fix_628_FPE_at_TIFFhowmany' into 'master' + Avoiding FPE (division by zero) for TIFFhowmany_32() and TIFFhowmany_64()... + + Closes #628 + + See merge request libtiff/libtiff!568 + +2024-03-15 Su_Laus + + Avoiding FPE (division by zero) for TIFFhowmany_32() and TIFFhowmany_64() macros by checking for denominator not zero before macros are executed. Fixes #628. + +2024-03-14 Even Rouault + + Merge branch 'fix_wrong_return_TIFFIsBigTIFF_if_swapping_case' into 'master' + Fix wrong return of TIFFIsBigTIFF() in case byte-swapping is acitve + + See merge request libtiff/libtiff!567 + +2024-03-13 Su_Laus + + Fix wrong return of TIFFIsBigTIFF() in case byte-swapping is acitve (i.e. little endian image on a big endian machine). + +2024-01-30 Even Rouault + + Merge branch 'master' into 'master' + Setting the TIFFFieldInfo field `set_field_type` should consider `field_writecount` not `field_readcount` + + See merge request libtiff/libtiff!544 + +2024-01-30 Timo Stüber + + Setting the TIFFFieldInfo field `set_field_type` should consider `field_writecount` not `field_readcount` + In most of the cases the field_writecount and field_readcount of the TIFFFieldInfo are equal. But they do not have to be the same. + + I encountered this issues when using an older release of Pillow. Since they use custom fields for decoding only, they set the readcount value to 0. As the result _TIFFSetGetType can not identify the type correctly and set TIFF_SETGET_UNDEFINED. + + Error Message: + ``` + TIFFLib: _TIFFWriteDirectorySec(): Rational2Double: .set_field_type is not 4 but 1. + ``` + + During the execution of TIFFMergeFieldInfo the fields get_field_type and set_field_type set. I guess the set_field_type should dependent on the field_writecount. + +2024-01-24 Even Rouault + + Merge branch 'avoid_memory_leaks_using_TIFFCreateDirectory' into 'master' + Avoiding memory leaks when using TIFFCreateDirectory() + + See merge request libtiff/libtiff!563 + +2024-01-24 Su_Laus + + Avoiding memory leaks when using TIFFCreateDirectory() by releasing the allocated memory in the tif-structure. + +2024-01-10 Even Rouault + + Merge branch 'WIN32' into 'master' + Use #ifdef _WIN32 to test for Windows, and tiffio.h: remove definition of __WIN32__ + + See merge request libtiff/libtiff!562 + +2024-01-08 Even Rouault + + test/raw_decode.c: remove likely ifdef tricks related to old compilers or unusual setups + + tif_jpeg.c/tif_ojpeg.c: remove likely ifdef tricks related to old compilers or unusual setups + + Remove _TIFFUInt64ToFloat() and _TIFFUInt64ToDouble() + + Remove support for _MSC_VER < 1500. + +2024-01-07 Even Rouault + + Use #ifdef _WIN32 to test for Windows, and tiffio.h: remove definition of __WIN32__ + +2023-12-20 Even Rouault + + Merge branch 'fix_579_non_terminated_ASCII_deletes_one_byte' into 'master' + Fixed issue with non-terminated ASCII arrays where the last character is overwritten (fixes #579) + + Closes #579 + + See merge request libtiff/libtiff!561 + +2023-12-20 Su_Laus + + For non-terminated ASCII arrays, the buffer is first enlarged before a NULL is set at the end to avoid deleting the last character. Fixes #579. Some editorials in tif_dir.c. + +2023-12-09 Even Rouault + + Merge branch 'fix_624_check_TIFFCreateAnonField_return' into 'master' + Fix 624: Check return value of _TIFFCreateAnonField() + + Closes #624 + + See merge request libtiff/libtiff!560 + +2023-12-01 Su_Laus + + Check return value of _TIFFCreateAnonField(). + Fixes #624 + +2023-11-27 Even Rouault + + Merge branch 'TIFFOpenOptionsSetMaxCumulatedMemAlloc' into 'master' + Add TIFFOpenOptionsSetMaxCumulatedMemAlloc() + + See merge request libtiff/libtiff!556 + +2023-11-27 Even Rouault + + Add TIFFOpenOptionsSetMaxCumulatedMemAlloc() + This function complements ``TIFFOpenOptionsSetMaxSingleMemAlloc()`` to define the maximum cumulated memory allocations in byte, for a given TIFF handle, that libtiff internal memory allocation functions are allowed. + +2023-11-23 Even Rouault + + Merge branch 'unity_clang_fixes' into 'master' + Fixes to avoid CLang warnings on unity builds + + See merge request libtiff/libtiff!558 + +2023-11-23 Even Rouault + + Fixes to avoid CLang warnings on unity builds. + +2023-11-22 Even Rouault + + Merge branch 'cmake_UNITY_BUILD' into 'master' + Changes to allow building with cmake -DCMAKE_UNITY_BUILD=ON + + See merge request libtiff/libtiff!557 + +2023-11-22 Even Rouault + + CI: test -DCMAKE_UNITY_BUILD=ON. + + Changes to allow building with cmake -DCMAKE_UNITY_BUILD=ON. + +2023-11-22 Even Rouault + + Merge branch 'manpage_506_TIFFClose_check_with_TIFFFlush' into 'master' + manpage: Note on using TIFFFlush() before TIFFClose() + + Closes #506 + + See merge request libtiff/libtiff!555 + +2023-11-16 Su_Laus + + manpage: Note on using TIFFFlush() before TIFFClose() to check that the data has been successfully written to the file. + Closes #506 + +2023-11-11 Even Rouault + + Merge branch 'manpage_621_TIFFOpenOptionsSetMaxSingleMemAlloc' into 'master' + manpage: Update TIFF documentation about TIFFOpenOptions.rst and memory limitting. + + Closes #621 + + See merge request libtiff/libtiff!553 + +2023-11-11 Even Rouault + + Merge branch 'rectify_some_shadowed_declarations' into 'master' + Rectify some shadowed declarations and warnings in tools and test modules. + + See merge request libtiff/libtiff!552 + +2023-11-11 Even Rouault + + Merge branch 'fix_TIFFRealloc_usage_to_TIFFReallocExt' into 'master' + Change internally used _TIFFRealloc() to _TIFFReallocExt() + + See merge request libtiff/libtiff!554 + +2023-11-11 Su_Laus + + Change internally used _TIFFRealloc() to _TIFFReallocExt(), which respects the TIFFOpenOptionsSetMaxSingleMemAlloc() limit. + +2023-11-11 Timothy Lyanguzov + + Fix typo. + +2023-11-09 Su_Laus + + manpage: Update TIFF documentation about TIFFOpenOptions.rst and TIFFOpenOptionsSetMaxSingleMemAlloc() usage and some other small fixes. + +2023-11-08 Su_Laus + + Rectify some shadowed declarations and warnings in tools and test modules. + +2023-11-04 Even Rouault + + Merge branch 'fix_583' into 'master' + tif_fax3.c: error out after a number of times end-of-file has been reached (fixes #583) + + Closes #583 + + See merge request libtiff/libtiff!547 + +2023-11-04 Even Rouault + + Merge branch 'fix_622' into 'master' + TIFFReadRGBAStrip/TIFFReadRGBATile: add more validation of col/row (fixes #622) + + Closes #622 + + See merge request libtiff/libtiff!546 + +2023-10-31 Even Rouault + + Merge branch 'extra_limit_getfilesize' into 'master' + tif_dirread.c: only issue TIFFGetFileSize() for large enough RAM requests + + See merge request libtiff/libtiff!551 + +2023-10-31 Even Rouault + + tif_dirread.c: only issue TIFFGetFileSize() for large enough RAM requests + +2023-10-31 Even Rouault + + Merge branch 'TIFFFetchDirectory_remove_useless_check' into 'master' + TIFFFetchDirectory(): remove useless allocsize vs filesize check + + See merge request libtiff/libtiff!550 + +2023-10-31 Even Rouault + + TIFFFetchDirectory(): remove useless allocsize vs filesize check. + CoverityScan rightly points that the max value for dircount16 * dirsize + is 4096 * 20. That's small enough not to do any check + +2023-10-31 Even Rouault + + Merge branch 'limit_getfilesize' into 'master' + tif_dirread.c: only issue TIFFGetFileSize() for large enough RAM requests + + See merge request libtiff/libtiff!549 + +2023-10-31 Even Rouault + + tif_dirread.c: only issue TIFFGetFileSize() for large enough RAM requests + Ammends 5320c9d89c054fa805d037d84c57da874470b01a + + This fixes a performance regression caught by the GDAL regression test + suite. + +2023-10-31 Even Rouault + + Merge branch 'tif_dirread-typo' into 'master' + tif_dirread.c: Fix typo: greather -> greater + + See merge request libtiff/libtiff!548 + +2023-10-31 Kurt Schwehr + + tif_dirread.c: Fix typo: greather -> greater. + +2023-10-31 Even Rouault + + Merge branch 'fix_614_check_mem_allocation_vs_filelength' into 'master' + Prevent some out-of-memory attacks + + See merge request libtiff/libtiff!545 + +2023-10-31 Su Laus + + Prevent some out-of-memory attacks. + Some small fuzzer files fake large amounts of data and provoke out-of-memory situations. For non-compressed data content / tags, out-of-memory can be prevented by comparing with the file size. + + At image reading, data size of some tags / data structures (StripByteCounts, StripOffsets, StripArray, TIFF directory) is compared with file size to prevent provoked out-of-memory attacks. + + See issue https://gitlab.com/libtiff/libtiff/-/issues/614#note_1602683857 + +2023-10-31 Even Rouault + + tif_fax3.c: error out after a number of times end-of-file has been reached (fixes #583) + + TIFFReadRGBAStrip/TIFFReadRGBATile: add more validation of col/row (fixes #622) + +2023-10-30 Even Rouault + + Merge branch 'fix_failed_subdirectory_read' into 'master' + #618: ensure absolute seeking is forced independent + + See merge request libtiff/libtiff!543 + +2023-10-25 Manuel Massing + + #618: ensure absolute seeking is forced independent of TIFFReadDirectory success. + This fixes TIFFSetDirectory calls for the case where + TIFFReadDirectory was unsuccessful. + +2023-10-17 Even Rouault + + Merge branch 'cmake' into 'master' + CMake: Fix TIFF_INCLUDE_DIRS + + See merge request libtiff/libtiff!541 + +2023-10-12 Even Rouault + + Merge branch 'fix_616' into 'master' + tif_lzw.c: avoid warning about misaligned address with UBSAN (fixes #616) + + Closes #616 + + See merge request libtiff/libtiff!542 + +2023-10-12 Even Rouault + + Merge branch 'tiffcp_cancel_ycbcr' into 'master' + tiffcp: replace PHOTOMETRIC_YCBCR with PHOTOMETRIC_RGB when outputing to... + + See merge request libtiff/libtiff!540 + +2023-10-12 Even Rouault + + tif_lzw.c: avoid warning about misaligned address with UBSAN (fixes #616) + The branch suppressed by this commit wasn't useful as I've verified that + with -O2 and -O3 and gcc or clang, doing a memcpy() + _byteswap_uint64() + generates exactly the same code as _byteswap_uint64(*ptr). + The warning with UBSAN thus only comes from UBSAN generating special code + to catch the misalignment, but is unlikely to cause any issue in + practice given the above observation. + +2023-10-12 Julien Schueller + + CMake: Fix TIFF_INCLUDE_DIRS. + +2023-10-08 Even Rouault + + tiffcp: preserve TIFFTAG_REFERENCEBLACKWHITE when doing YCbCr JPEG -> YCbCr JPEG + +2023-10-07 Even Rouault + + tiffcp: replace PHOTOMETRIC_YCBCR with PHOTOMETRIC_RGB when outputing to compression != JPEG (refs #571) + +2023-10-05 Even Rouault + + Merge branch 'kmilos-master-patch-42063' into 'master' + CMake: MinGW compilers don't need a .def file for shared library + + See merge request libtiff/libtiff!448 + +2023-10-05 Even Rouault + + Merge branch 'kmilos-master-patch-64997' into 'master' + CMake: move libdeflate and Lerc to Requires.private + + See merge request libtiff/libtiff!536 + +2023-10-05 Even Rouault + + Merge branch 'clarify_archive' into 'master' + Doc: clarify unsupported (still in tarball) and archived (only in git) utilities + + See merge request libtiff/libtiff!532 + +2023-10-05 Even Rouault + + Merge branch 'fix_571_alternative' into 'master' + tiffcp: Setting the correct photometric interpretation for the output image... + + Closes #571 + + See merge request libtiff/libtiff!539 + +2023-10-04 Even Rouault + + tiffcp: do not copy tags YCBCRCOEFFICIENTS, YCBCRSUBSAMPLING, YCBCRPOSITIONING, REFERENCEBLACKWHITE. Only set TIFFTAG_YCBCRSUBSAMPLING when generating YCbCr JPEG + + tiffcp: Setting the correct photometric interpretation for the output image when converting JPEG-YCBCR to JPEG-RGB images. + Closes #571 + +2023-09-28 Miloš Komarčević + + CMake: move libdeflate and Lerc to Requires.private. + +2023-09-27 Even Rouault + + Merge branch 'kmilos-windres' into 'master' + CMake: enable resource compilation on all Windows + + See merge request libtiff/libtiff!537 + +2023-09-27 Miloš Komarčević + + CMake: enable resource compilation on all Windows. + +2023-09-15 Even Rouault + + Merge branch 'fix_608' into 'master' + tif_dirinfo.c: re-enable TIFFTAG_EP_CFAREPEATPATTERNDIM and TIFFTAG_EP_CFAPATTERN tags (fixes #608) + + Closes #608 + + See merge request libtiff/libtiff!534 + +2023-09-15 Even Rouault + + tif_dirinfo.c: re-enable TIFFTAG_EP_CFAREPEATPATTERNDIM and TIFFTAG_EP_CFAPATTERN tags (fixes #608) + +2023-09-09 Even Rouault + + Merge branch 'fix_606_tiffcp_check_also_input_compression_codec' into 'master' + tiffcp: Fixes #606. Check also codec of input image, not only from output image. + + Closes #606 + + See merge request libtiff/libtiff!533 + +2023-09-09 Su_Laus + + Check also if codec of input image is available, independently from codec check of output image and return with error if not. Fixes #606. + +2023-09-08 Even Rouault + + Doc: clarify unsupported (still in tarball) and archived (only in git) utilities + +2023-09-08 Even Rouault + + Merge branch 'update_release_date' into 'master' + Update RELEASE-DATE + + See merge request libtiff/libtiff!531 + +2023-09-08 Even Rouault + + Update RELEASE-DATE. + +2023-09-08 Even Rouault + + Merge branch 'fix_605' into 'master' + autoconf.ac: fix detection of windows.h for mingw (fixes #605) + + Closes #605 + + See merge request libtiff/libtiff!530 + +2023-09-07 Even Rouault + + autoconf.ac: fix detection of windows.h for mingw (fixes #605) + +2023-09-06 Even Rouault + + Merge branch 'prepare_v4_6_0' into 'master' + Prepare for libtiff 4.6.0 release + + See merge request libtiff/libtiff!528 + +2023-09-05 Even Rouault + + doc/index.rst: add warning about tools removal. + +2023-09-05 Even Rouault + + Merge branch 'fix_603_readme_doc_reference_update' into 'master' + Update documentation reference within README.md. Fixes #603. + + Closes #603 + + See merge request libtiff/libtiff!529 + +2023-09-05 Su_Laus + + Update documentation reference within README.md. Fixes #603. + +2023-09-05 Even Rouault + + Fix references to mailing list. + 2023-09-05 Even Rouault libtiff v4.6.0 released @@ -299,7 +1882,7 @@ Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=59751 In 738e0409 (refs #575), we disabled DNG / EP tags, but there was a - special proessing for TIFFTAG_EP_BATTERYLEVEL that must be disabled + special processing for TIFFTAG_EP_BATTERYLEVEL that must be disabled since the tag is no longer defined. 2023-06-09 Su_Laus @@ -395,8 +1978,8 @@ tif_dirinfo.c: disable DNG 1.2->1.6 tags. They were added per b90b20d36d7833f54a1f3014c324f6c21b988006 but it has been found in https://gitlab.com/libtiff/libtiff/-/issues/575 that it - could cause compatibity issues with libtiff users, so this addition - should be defered for a feature release (likely 4.6.0) and not a patch one. + could cause compatibility issues with libtiff users, so this addition + should be deferred for a feature release (likely 4.6.0) and not a patch one. Fixes #575 @@ -576,7 +2159,7 @@ 2023-05-06 Even Rouault Merge branch 'fix_548' into 'master' - LZWDecode(): avoid crash when trying to read again from a strip whith a... + LZWDecode(): avoid crash when trying to read again from a strip with a... Closes #548 @@ -610,7 +2193,7 @@ 2023-04-29 Even Rouault - LZWDecode(): avoid crash when trying to read again from a strip whith a missing end-of-information marker (fixes #548) + LZWDecode(): avoid crash when trying to read again from a strip with a missing end-of-information marker (fixes #548) 2023-04-25 Su_Laus @@ -1339,7 +2922,7 @@ Use structures that can be extended as extra argument. - Leverages and ammends https://gitlab.com/libtiff/libtiff/-/merge_requests/409 + Leverages and amends https://gitlab.com/libtiff/libtiff/-/merge_requests/409 2022-11-21 Even Rouault @@ -2077,7 +3660,7 @@ to { TIFFTAG_INTEROPERABILITYIFD, 1, 1, TIFF_IFD8, 0, TIFF_SETGET_IFD8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 0, 0, "InteroperabilityIFDOffset", NULL }, - However, if those tags schould not be handled by LibTiff because they are deamed as abandoned or unwanted tags, those tags need to be defined with FIELD_IGNORE instead of FIELD_CUSTOM and keeping set_field_type = TIFF_SETGET_UNDEFINED + However, if those tags should not be handled by LibTiff because they are deemed as abandoned or unwanted tags, those tags need to be defined with FIELD_IGNORE instead of FIELD_CUSTOM and keeping set_field_type = TIFF_SETGET_UNDEFINED 2022-07-01 Su_Laus @@ -2185,7 +3768,7 @@ tif_predict.c: make horAcc8() work with icc (ICC) 2021.6.0 20220226 -O2. For a reason I don't understand, recent ICC generates wrong code in -O2 mode for the stride = 3 and 4 cases. The modified code is more - straightfoward, so go for it. + straightforward, so go for it. 2022-06-19 Roger Leigh @@ -2442,7 +4025,7 @@ Include stdlib.h in tif_lzw.c. In `tif_lzw.c`, a call is made to `_byteswap_uint64`. This is declared in `stdlib.h`. `stdlib.h` is not included in `tib_lzw.c`, so a name error may occur. - This change adds `#include stdlib.h` to `tif_lzw.c`, to prevent a name error from occuring when `stdlib.h` is not included. + This change adds `#include stdlib.h` to `tif_lzw.c`, to prevent a name error from occurring when `stdlib.h` is not included. 2022-05-29 Roger Leigh @@ -2662,7 +4245,7 @@ 2022-04-22 Even Rouault - tif_lzw.c: fix potential out-of-bounds error when trying to read in the same tile/strip after an error has occured (fixes #410) + tif_lzw.c: fix potential out-of-bounds error when trying to read in the same tile/strip after an error has occurred (fixes #410) 2022-04-06 Su_Laus @@ -3035,7 +4618,7 @@ 2022-02-11 Even Rouault Merge branch 'predictor_2_64bit' into 'master' - Predictor 2 (horizontal differenciation): support 64-bit + Predictor 2 (horizontal differentiation): support 64-bit See merge request libtiff/libtiff!296 @@ -3054,7 +4637,7 @@ 2022-02-09 Even Rouault - Predictor 2 (horizontal differenciation): support 64-bit. + Predictor 2 (horizontal differentiation): support 64-bit. There's no reason not to support 64-bit. The TIFF 6 specification doesn't say anything about that (and even mention 4-bit, which we don't support) @@ -3237,8 +4820,8 @@ 2021-12-13 Even Rouault OJPEG: avoid assertion when using TIFFReadScanline() (fixes #337) - Note: my analyis of the issue would be that the use of the scanline API - is currently propably broken with OJPEG. + Note: my analysis of the issue would be that the use of the scanline API + is currently probably broken with OJPEG. 2021-12-10 Even Rouault @@ -3492,7 +5075,7 @@ 2021-09-23 Even Rouault TIFFAppendToStrip(): fix rewrite-in-place logic. - reproducable in particular with packbits compression. + reproducible in particular with packbits compression. Fixes https://github.com/OSGeo/gdal/issues/4538 @@ -3960,7 +5543,7 @@ 2021-03-07 Antonio Valentino Add LERC plugin. - The lerc plugin code has been copyed form GDAL. + The lerc plugin code has been copied from GDAL. 2021-03-06 Roger Leigh @@ -4160,7 +5743,7 @@ Correct include order. - Eliminate implict fallthrough usage. + Eliminate implicit fallthrough usage. Use simple loops in place of manual loop unrolling. Rely on the compiler optimiser to unroll loops when appropriate. @@ -4422,7 +6005,7 @@ 2021-01-18 Even Rouault Merge branch 'tiffcmp' into 'master' - tiffcmp: fix comparaison with pixels that are fractional number of bytes + tiffcmp: fix comparison with pixels that are fractional number of bytes Closes #53 @@ -4438,8 +6021,8 @@ 2021-01-15 Thomas Bernard - tiffcmp: fix comparaison with pixels that are fractional number of bytes - For exemple : 4bits per sample + 3 samples per pixel => 1.5 bytes per pixel + tiffcmp: fix comparison with pixels that are fractional number of bytes + For example : 4bits per sample + 3 samples per pixel => 1.5 bytes per pixel tiff2ps: exit the loop in case of error. fixes #232 @@ -4634,7 +6217,7 @@ 2020-12-31 Kurt Schwehr custom_dir_EXIF_231.c: dos2unix and codespell. - additonal, Varable, greather, alwasy + additional, Variable, greater, always 2020-12-31 Kurt Schwehr @@ -7740,7 +9323,7 @@ 2017-11-23 Roger Leigh - appveyor: Correct path for git clone and skip artefact archival. + appveyor: Correct path for git clone and skip artifact archival. 2017-11-22 Roger Leigh diff --git a/3rdparty/libtiff/RELEASE-DATE b/3rdparty/libtiff/RELEASE-DATE index 68d943433e..2abf40291e 100644 --- a/3rdparty/libtiff/RELEASE-DATE +++ b/3rdparty/libtiff/RELEASE-DATE @@ -1 +1 @@ -20230908 +20240911 diff --git a/3rdparty/libtiff/tif_aux.c b/3rdparty/libtiff/tif_aux.c index 49855bb0b2..e9606a42e0 100644 --- a/3rdparty/libtiff/tif_aux.c +++ b/3rdparty/libtiff/tif_aux.c @@ -385,53 +385,6 @@ int TIFFGetFieldDefaulted(TIFF *tif, uint32_t tag, ...) return (ok); } -struct _Int64Parts -{ - int32_t low, high; -}; - -typedef union -{ - struct _Int64Parts part; - int64_t value; -} _Int64; - -float _TIFFUInt64ToFloat(uint64_t ui64) -{ - _Int64 i; - - i.value = ui64; - if (i.part.high >= 0) - { - return (float)i.value; - } - else - { - long double df; - df = (long double)i.value; - df += 18446744073709551616.0; /* adding 2**64 */ - return (float)df; - } -} - -double _TIFFUInt64ToDouble(uint64_t ui64) -{ - _Int64 i; - - i.value = ui64; - if (i.part.high >= 0) - { - return (double)i.value; - } - else - { - long double df; - df = (long double)i.value; - df += 18446744073709551616.0; /* adding 2**64 */ - return (double)df; - } -} - float _TIFFClampDoubleToFloat(double val) { if (val > FLT_MAX) diff --git a/3rdparty/libtiff/tif_close.c b/3rdparty/libtiff/tif_close.c index 907d7f139b..d6bb7f1d7c 100644 --- a/3rdparty/libtiff/tif_close.c +++ b/3rdparty/libtiff/tif_close.c @@ -110,6 +110,14 @@ void TIFFCleanup(TIFF *tif) _TIFFfreeExt(tif, tif->tif_fieldscompat); } + if (tif->tif_cur_cumulated_mem_alloc != 0) + { + TIFFErrorExtR(tif, "TIFFCleanup", + "tif_cur_cumulated_mem_alloc = %" PRIu64 " whereas it " + "should be 0", + (uint64_t)tif->tif_cur_cumulated_mem_alloc); + } + _TIFFfreeExt(NULL, tif); } diff --git a/3rdparty/libtiff/tif_color.c b/3rdparty/libtiff/tif_color.c index 2d7dcac6fe..a52fdacba5 100644 --- a/3rdparty/libtiff/tif_color.c +++ b/3rdparty/libtiff/tif_color.c @@ -89,7 +89,7 @@ void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, uint32_t *r, uint32_t *g, uint32_t *b) { - int i; + size_t i; float Yr, Yg, Yb; float *matrix = &cielab->display.d_mat[0][0]; @@ -109,16 +109,16 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, Yb = TIFFmin(Yb, cielab->display.d_YCB); /* Turn luminosity to colour value. */ - i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep); - i = TIFFmin(cielab->range, i); + i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep); + i = TIFFmin((size_t)cielab->range, i); *r = RINT(cielab->Yr2r[i]); - i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); - i = TIFFmin(cielab->range, i); + i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep); + i = TIFFmin((size_t)cielab->range, i); *g = RINT(cielab->Yg2g[i]); - i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); - i = TIFFmin(cielab->range, i); + i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep); + i = TIFFmin((size_t)cielab->range, i); *b = RINT(cielab->Yb2b[i]); /* Clip output. */ @@ -135,7 +135,7 @@ void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display, float *refWhite) { - int i; + size_t i; double dfGamma; cielab->range = CIELABTORGB_TABLE_RANGE; @@ -146,7 +146,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display, dfGamma = 1.0 / cielab->display.d_gammaR; cielab->rstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for (i = 0; i <= cielab->range; i++) + for (i = 0; i <= (size_t)cielab->range; i++) { cielab->Yr2r[i] = cielab->display.d_Vrwr * ((float)pow((double)i / cielab->range, dfGamma)); @@ -156,7 +156,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display, dfGamma = 1.0 / cielab->display.d_gammaG; cielab->gstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for (i = 0; i <= cielab->range; i++) + for (i = 0; i <= (size_t)cielab->range; i++) { cielab->Yg2g[i] = cielab->display.d_Vrwg * ((float)pow((double)i / cielab->range, dfGamma)); @@ -166,7 +166,7 @@ int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display, dfGamma = 1.0 / cielab->display.d_gammaB; cielab->bstep = (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; - for (i = 0; i <= cielab->range; i++) + for (i = 0; i <= (size_t)cielab->range; i++) { cielab->Yb2b[i] = cielab->display.d_Vrwb * ((float)pow((double)i / cielab->range, dfGamma)); diff --git a/3rdparty/libtiff/tif_config.h.cmake.in b/3rdparty/libtiff/tif_config.h.cmake.in index 62a4c7305a..645cb6b321 100644 --- a/3rdparty/libtiff/tif_config.h.cmake.in +++ b/3rdparty/libtiff/tif_config.h.cmake.in @@ -40,6 +40,18 @@ /* Define to 1 if you have the `getopt' function. */ #cmakedefine HAVE_GETOPT 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GLUT_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GLUT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GLU_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_GL_GL_H 1 + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_IO_H 1 @@ -49,6 +61,12 @@ /* Define to 1 if you have the `mmap' function. */ #cmakedefine HAVE_MMAP 1 +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENGL_GLU_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_OPENGL_GL_H 1 + /* Define to 1 if you have the `setmode' function. */ #cmakedefine HAVE_SETMODE 1 diff --git a/3rdparty/libtiff/tif_dir.c b/3rdparty/libtiff/tif_dir.c index 8500621837..459f9696fd 100644 --- a/3rdparty/libtiff/tif_dir.c +++ b/3rdparty/libtiff/tif_dir.c @@ -211,7 +211,7 @@ static uint16_t countInkNamesString(TIFF *tif, uint32_t slen, const char *s) } bad: TIFFErrorExtR(tif, "TIFFSetField", - "%s: Invalid InkNames value; no NUL at given buffer end " + "%s: Invalid InkNames value; no null at given buffer end " "location %" PRIu32 ", after %" PRIu16 " ink", tif->tif_name, slen, i); return (0); @@ -1652,6 +1652,17 @@ void TIFFFreeDirectory(TIFF *tif) _TIFFmemset(&(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset(&(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); + + /* Reset some internal parameters for IFD data size checking. */ + tif->tif_dir.td_dirdatasize_read = 0; + tif->tif_dir.td_dirdatasize_write = 0; + if (tif->tif_dir.td_dirdatasize_offsets != NULL) + { + _TIFFfreeExt(tif, tif->tif_dir.td_dirdatasize_offsets); + tif->tif_dir.td_dirdatasize_offsets = NULL; + tif->tif_dir.td_dirdatasize_Noffsets = 0; + } + tif->tif_dir.td_iswrittentofile = FALSE; } #undef CleanupField @@ -1676,18 +1687,23 @@ TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc extender) */ int TIFFCreateDirectory(TIFF *tif) { + /* Free previously allocated memory and setup default values. */ + TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); tif->tif_diroff = 0; tif->tif_nextdiroff = 0; tif->tif_curoff = 0; tif->tif_row = (uint32_t)-1; tif->tif_curstrip = (uint32_t)-1; + tif->tif_dir.td_iswrittentofile = FALSE; return 0; } int TIFFCreateCustomDirectory(TIFF *tif, const TIFFFieldArray *infoarray) { + /* Free previously allocated memory and setup default values. */ + TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); /* @@ -1848,7 +1864,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (((uint64_t)poffa != poff) || (poffb < poffa) || (poffb < (tmsize_t)sizeof(uint16_t)) || (poffb > tif->tif_size)) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); *nextdiroff = 0; return (0); } @@ -1877,14 +1895,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, uint16_t dircount16; if (poff > (uint64_t)TIFF_TMSIZE_T_MAX - sizeof(uint64_t)) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } poffa = (tmsize_t)poff; poffb = poffa + sizeof(uint64_t); if (poffb > tif->tif_size) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } _TIFFmemcpy(&dircount64, tif->tif_base + poffa, sizeof(uint64_t)); @@ -1926,8 +1948,9 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (!SeekOK(tif, *nextdiroff) || !ReadOK(tif, &dircount, sizeof(uint16_t))) { - TIFFErrorExtR(tif, module, "%s: Error fetching directory count", - tif->tif_name); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) @@ -1953,15 +1976,18 @@ static int TIFFAdvanceDirectory(TIFF *tif, uint64_t *nextdiroff, uint64_t *off, if (!SeekOK(tif, *nextdiroff) || !ReadOK(tif, &dircount64, sizeof(uint64_t))) { - TIFFErrorExtR(tif, module, "%s: Error fetching directory count", - tif->tif_name); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&dircount64); if (dircount64 > 0xFFFF) { - TIFFErrorExtR(tif, module, "Error fetching directory count"); + TIFFErrorExtR(tif, module, + "%s:%d: %s: Error fetching directory count", + __FILE__, __LINE__, tif->tif_name); return (0); } dircount16 = (uint16_t)dircount64; @@ -2018,6 +2044,8 @@ tdir_t TIFFNumberOfDirectories(TIFF *tif) { ++n; } + /* Update number of main-IFDs in file. */ + tif->tif_curdircount = n; return (n); } @@ -2100,7 +2128,19 @@ int TIFFSetDirectory(TIFF *tif, tdir_t dirn) tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; else tif->tif_curdir--; - return (TIFFReadDirectory(tif)); + + tdir_t curdir = tif->tif_curdir; + + int retval = TIFFReadDirectory(tif); + + if (!retval && tif->tif_curdir == curdir) + { + /* If tif_curdir has not be incremented, TIFFFetchDirectory() in + * TIFFReadDirectory() has failed and tif_curdir shall be set + * specifically. */ + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; + } + return (retval); } /* @@ -2125,8 +2165,11 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) int8_t probablySubIFD = 0; if (diroff == 0) { - /* Special case to invalidate the tif_lastdiroff member. */ + /* Special case to set tif_diroff=0, which is done in + * TIFFReadDirectory() below to indicate that the currently read IFD is + * treated as a new, fresh IFD. */ tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; + tif->tif_dir.td_iswrittentofile = FALSE; } else { @@ -2136,32 +2179,40 @@ int TIFFSetSubDirectory(TIFF *tif, uint64_t diroff) probablySubIFD = 1; } /* -1 because TIFFReadDirectory() will increment tif_curdir. */ - tif->tif_curdir = - curdir == 0 ? TIFF_NON_EXISTENT_DIR_NUMBER : curdir - 1; + if (curdir >= 1) + tif->tif_curdir = curdir - 1; + else + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; } + curdir = tif->tif_curdir; tif->tif_nextdiroff = diroff; retval = TIFFReadDirectory(tif); - /* If failed, curdir was not incremented in TIFFReadDirectory(), so set it - * back, but leave it for diroff==0. */ - if (!retval && diroff != 0) + + /* tif_curdir is incremented in TIFFReadDirectory(), but if it has not been + * incremented, TIFFFetchDirectory() has failed there and tif_curdir shall + * be set specifically. */ + if (!retval && diroff != 0 && tif->tif_curdir == curdir) { - if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER) - tif->tif_curdir = 0; - else - tif->tif_curdir++; + tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; } - if (retval && probablySubIFD) + + if (probablySubIFD) { - /* Reset IFD list to start new one for SubIFD chain and also start - * SubIFD chain with tif_curdir=0. */ - _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */ - tif->tif_curdir = 0; /* first directory of new chain */ - /* add this offset to new IFD list */ - _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff); + if (retval) + { + /* Reset IFD list to start new one for SubIFD chain and also start + * SubIFD chain with tif_curdir=0 for IFD loop checking. */ + /* invalidate IFD loop lists */ + _TIFFCleanupIFDOffsetAndNumberMaps(tif); + tif->tif_curdir = 0; /* first directory of new chain */ + /* add this offset to new IFD list */ + _TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, diroff); + } /* To be able to return from SubIFD or custom-IFD to main-IFD */ tif->tif_setdirectory_force_absolute = TRUE; } + return (retval); } @@ -2257,9 +2308,11 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn) } else { + /* Need local swap because nextdir has to be used unswapped below. */ + uint64_t nextdir64 = nextdir; if (tif->tif_flags & TIFF_SWAB) - TIFFSwabLong8(&nextdir); - if (!WriteOK(tif, &nextdir, sizeof(uint64_t))) + TIFFSwabLong8(&nextdir64); + if (!WriteOK(tif, &nextdir64, sizeof(uint64_t))) { TIFFErrorExtR(tif, module, "Error writing directory link"); return (0); @@ -2303,6 +2356,10 @@ int TIFFUnlinkDirectory(TIFF *tif, tdir_t dirn) tif->tif_row = (uint32_t)-1; tif->tif_curstrip = (uint32_t)-1; tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; + if (tif->tif_curdircount > 0) + tif->tif_curdircount--; + else + tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER; _TIFFCleanupIFDOffsetAndNumberMaps(tif); /* invalidate IFD loop lists */ return (1); } diff --git a/3rdparty/libtiff/tif_dir.h b/3rdparty/libtiff/tif_dir.h index 9eaf22f8e6..ffad085e02 100644 --- a/3rdparty/libtiff/tif_dir.h +++ b/3rdparty/libtiff/tif_dir.h @@ -65,6 +65,12 @@ typedef struct tif_dirread.c */ } TIFFDirEntry; +typedef struct +{ + uint64_t offset; + uint64_t length; +} TIFFEntryOffsetAndLength; /* auxiliary for evaluating size of IFD data */ + /* * Internal format of a TIFF directory entry. */ @@ -115,6 +121,9 @@ typedef struct #ifdef STRIPBYTECOUNTSORTED_UNUSED int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ #endif + /* Be aware that the parameters of td_stripoffset_entry and + * td_stripbytecount_entry are swapped but tdir_offset is not + * and has to be swapped when used. */ TIFFDirEntry td_stripoffset_entry; /* for deferred loading */ TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */ uint16_t td_nsubifd; @@ -135,6 +144,24 @@ typedef struct unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */ + + unsigned char + td_iswrittentofile; /* indicates if current IFD is present on file */ + + /* LibTIFF writes all data that does not fit into the IFD entries directly + * after the IFD tag entry part. When reading, only the IFD data directly + * and continuously behind the IFD tags is taken into account for the IFD + * data size.*/ + uint64_t td_dirdatasize_write; /* auxiliary for evaluating size of IFD data + to be written */ + uint64_t td_dirdatasize_read; /* auxiliary for evaluating size of IFD data + read from file */ + uint32_t td_dirdatasize_Noffsets; /* auxiliary counter for + tif_dir.td_dirdatasize_offsets array */ + TIFFEntryOffsetAndLength + *td_dirdatasize_offsets; /* auxiliary array for all offsets of IFD tag + entries with data outside the IFD tag + entries. */ } TIFFDirectory; /* @@ -308,11 +335,10 @@ extern "C" TIFFDataType field_type; /* type of associated data */ uint32_t field_anonymous; /* if true, this is a unknown / anonymous tag */ - TIFFSetGetFieldType - set_field_type; /* type to be passed to TIFFSetField */ - TIFFSetGetFieldType - get_field_type; /* type to be passed to TIFFGetField */ - unsigned short field_bit; /* bit in fieldsset bit vector */ + TIFFSetGetFieldType set_field_type; /* type to be passed to TIFFSetField + and TIFFGetField*/ + TIFFSetGetFieldType get_field_type; /* not used */ + unsigned short field_bit; /* bit in fieldsset bit vector */ unsigned char field_oktochange; /* if true, can change while writing */ unsigned char field_passcount; /* if true, pass dir count on set */ char *field_name; /* ASCII name */ diff --git a/3rdparty/libtiff/tif_dirinfo.c b/3rdparty/libtiff/tif_dirinfo.c index 0e705e81e3..432e6e1e44 100644 --- a/3rdparty/libtiff/tif_dirinfo.c +++ b/3rdparty/libtiff/tif_dirinfo.c @@ -213,8 +213,6 @@ static const TIFFField tiffFields[] = { {TIFFTAG_CURRENTPREPROFILEMATRIX, -1, -1, TIFF_SRATIONAL, 0, TIFF_SETGET_C16_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CurrentPreProfileMatrix", NULL}, {TIFFTAG_PERSAMPLE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_UNDEFINED, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "PerSample", NULL}, #if 0 - /* TODO: revert above #if 0 for TIFF 4.6.0 */ - /* begin DNG 1.2.0.0 tags */ {TIFFTAG_COLORIMETRICREFERENCE, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ColorimetricReference", NULL}, {TIFFTAG_CAMERACALIBRATIONSIGNATURE, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "CameraCalibrationSignature", NULL}, @@ -282,9 +280,11 @@ static const TIFFField tiffFields[] = { {TIFFTAG_ILLUMINANTDATA2, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData2", NULL}, {TIFFTAG_ILLUMINANTDATA3, -3, -3, TIFF_UNDEFINED, 0, TIFF_SETGET_C32_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "IlluminantData3", NULL}, /* end DNG tags */ +#endif /* begin TIFF/EP tags */ {TIFFTAG_EP_CFAREPEATPATTERNDIM, 2, 2, TIFF_SHORT, 0, TIFF_SETGET_C0_UINT16, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP CFARepeatPatternDim", NULL}, {TIFFTAG_EP_CFAPATTERN, -1, -1, TIFF_BYTE, 0, TIFF_SETGET_C16_UINT8, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 1, "EP CFAPattern", NULL}, +#if 0 /* TIFFTAG_EP_BATTERYLEVEL can be RATIONAL or ASCII. * LibTiff defines it as ASCII and converts RATIONAL to an ASCII string. */ {TIFFTAG_EP_BATTERYLEVEL, -1, -1, TIFF_ASCII, 0, TIFF_SETGET_ASCII, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "EP BatteryLevel", NULL}, @@ -374,7 +374,7 @@ static const TIFFField exifFields[] = { {EXIFTAG_BRIGHTNESSVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "BrightnessValue", NULL}, {EXIFTAG_EXPOSUREBIASVALUE, 1, 1, TIFF_SRATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "ExposureBiasValue", NULL}, {EXIFTAG_MAXAPERTUREVALUE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "MaxApertureValue", NULL}, - /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance! + /*--: EXIFTAG_SUBJECTDISTANCE: LibTiff returns value of "-1" if numerator equals 4294967295 (0xFFFFFFFF) to indicate infinite distance! * However, there are two other EXIF tags where numerator indicates a special value and six other cases where the denominator indicates special values, * which are not treated within LibTiff!! */ {EXIFTAG_SUBJECTDISTANCE, 1, 1, TIFF_RATIONAL, 0, TIFF_SETGET_FLOAT, TIFF_SETGET_UNDEFINED, FIELD_CUSTOM, 1, 0, "SubjectDistance", NULL}, @@ -887,7 +887,7 @@ const TIFFField *_TIFFFindOrRegisterField(TIFF *tif, uint32_t tag, if (fld == NULL) { fld = _TIFFCreateAnonField(tif, tag, dt); - if (!_TIFFMergeFields(tif, fld, 1)) + if (fld == NULL || !_TIFFMergeFields(tif, fld, 1)) return NULL; } @@ -1197,12 +1197,24 @@ int TIFFMergeFieldInfo(TIFF *tif, const TIFFFieldInfo info[], uint32_t n) for (i = 0; i < n; i++) { tp->field_tag = info[i].field_tag; + if (info[i].field_readcount < TIFF_VARIABLE2 || + info[i].field_readcount == 0 || + info[i].field_writecount < TIFF_VARIABLE2 || + info[i].field_writecount == 0) + { + /* The fields (field_readcount) and (field_writecount) may use the + * values TIFF_VARIABLE (-1), TIFF_SPP (-2), TIFF_VARIABLE2 (-3). */ + TIFFErrorExtR(tif, module, + "The value of field_readcount and field_writecount " + "must be greater than or equal to -3 and not zero."); + return -1; + } tp->field_readcount = info[i].field_readcount; tp->field_writecount = info[i].field_writecount; tp->field_type = info[i].field_type; tp->field_anonymous = 0; tp->set_field_type = - _TIFFSetGetType(info[i].field_type, info[i].field_readcount, + _TIFFSetGetType(info[i].field_type, info[i].field_writecount, info[i].field_passcount); tp->get_field_type = _TIFFSetGetType(info[i].field_type, info[i].field_readcount, diff --git a/3rdparty/libtiff/tif_dirread.c b/3rdparty/libtiff/tif_dirread.c index 2c49dc6aa0..3d94ea7d4f 100644 --- a/3rdparty/libtiff/tif_dirread.c +++ b/3rdparty/libtiff/tif_dirread.c @@ -1016,16 +1016,7 @@ TIFFReadDirEntryFloat(TIFF *tif, TIFFDirEntry *direntry, float *value) err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m); if (err != TIFFReadDirEntryErrOk) return (err); -#if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support conversion - * of 64-bit integers into floating point - * values. - */ - *value = _TIFFUInt64ToFloat(m); -#else *value = (float)m; -#endif return (TIFFReadDirEntryErrOk); } case TIFF_SLONG8: @@ -1130,16 +1121,7 @@ TIFFReadDirEntryDouble(TIFF *tif, TIFFDirEntry *direntry, double *value) err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m); if (err != TIFFReadDirEntryErrOk) return (err); -#if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support conversion - * of 64-bit integers into floating point - * values. - */ - *value = _TIFFUInt64ToDouble(m); -#else *value = (double)m; -#endif return (TIFFReadDirEntryErrOk); } case TIFF_SLONG8: @@ -1308,6 +1290,24 @@ TIFFReadDirEntryArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry, datasize = (*count) * typesize; assert((tmsize_t)datasize > 0); + if (datasize > 100 * 1024 * 1024) + { + /* Before allocating a huge amount of memory for corrupted files, check + * if size of requested memory is not greater than file size. + */ + const uint64_t filesize = TIFFGetFileSize(tif); + if (datasize > filesize) + { + TIFFWarningExtR(tif, "ReadDirEntryArray", + "Requested memory size for tag %d (0x%x) %" PRIu32 + " is greater than filesize %" PRIu64 + ". Memory not allocated, tag not read", + direntry->tdir_tag, direntry->tdir_tag, datasize, + filesize); + return (TIFFReadDirEntryErrAlloc); + } + } + if (isMapped(tif) && datasize > (uint64_t)tif->tif_size) return TIFFReadDirEntryErrIo; @@ -2886,16 +2886,7 @@ TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value) { if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(ma); -#if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support - * conversion of 64-bit integers into - * floating point values. - */ - *mb++ = _TIFFUInt64ToFloat(*ma++); -#else *mb++ = (float)(*ma++); -#endif } } break; @@ -3131,16 +3122,7 @@ TIFFReadDirEntryDoubleArray(TIFF *tif, TIFFDirEntry *direntry, double **value) { if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(ma); -#if defined(__WIN32__) && (_MSC_VER < 1500) - /* - * XXX: MSVC 6.0 does not support - * conversion of 64-bit integers into - * floating point values. - */ - *mb++ = _TIFFUInt64ToDouble(*ma++); -#else *mb++ = (double)(*ma++); -#endif } } break; @@ -4095,6 +4077,155 @@ static int ByteCountLooksBad(TIFF *tif) return 0; } +/* + * To evaluate the IFD data size when reading, save the offset and data size of + * all data that does not fit into the IFD entries themselves. + */ +static bool EvaluateIFDdatasizeReading(TIFF *tif, TIFFDirEntry *dp) +{ + const uint64_t data_width = TIFFDataWidth(dp->tdir_type); + if (data_width != 0 && dp->tdir_count > UINT64_MAX / data_width) + { + TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading", + "Too large IFD data size"); + return false; + } + const uint64_t datalength = dp->tdir_count * data_width; + if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U)) + { + if (tif->tif_dir.td_dirdatasize_read > UINT64_MAX - datalength) + { + TIFFErrorExtR(tif, "EvaluateIFDdatasizeReading", + "Too large IFD data size"); + return false; + } + tif->tif_dir.td_dirdatasize_read += datalength; + if (!(tif->tif_flags & TIFF_BIGTIFF)) + { + /* The offset of TIFFDirEntry are not swapped when read in. That has + * to be done when used. */ + uint32_t offset = dp->tdir_offset.toff_long; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong(&offset); + tif->tif_dir + .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets] + .offset = (uint64_t)offset; + } + else + { + tif->tif_dir + .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets] + .offset = dp->tdir_offset.toff_long8; + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabLong8( + &tif->tif_dir + .td_dirdatasize_offsets[tif->tif_dir + .td_dirdatasize_Noffsets] + .offset); + } + tif->tif_dir + .td_dirdatasize_offsets[tif->tif_dir.td_dirdatasize_Noffsets] + .length = datalength; + tif->tif_dir.td_dirdatasize_Noffsets++; + } + return true; +} + +/* + * Compare function for qsort() sorting TIFFEntryOffsetAndLength array entries. + */ +static int cmpTIFFEntryOffsetAndLength(const void *a, const void *b) +{ + const TIFFEntryOffsetAndLength *ta = (const TIFFEntryOffsetAndLength *)a; + const TIFFEntryOffsetAndLength *tb = (const TIFFEntryOffsetAndLength *)b; + /* Compare offsets */ + if (ta->offset > tb->offset) + return 1; + else if (ta->offset < tb->offset) + return -1; + else + return 0; +} + +/* + * Determine the IFD data size after reading an IFD from the file that can be + * overwritten and saving it in tif_dir.td_dirdatasize_read. This data size + * includes the IFD entries themselves as well as the data that does not fit + * directly into the IFD entries but is located directly after the IFD entries + * in the file. + */ +static void CalcFinalIFDdatasizeReading(TIFF *tif, uint16_t dircount) +{ + /* IFD data size is only needed if file-writing is enabled. + * This also avoids the seek() to EOF to determine the file size, which + * causes the stdin-streaming-friendly mode of libtiff for GDAL to fail. */ + if (tif->tif_mode == O_RDONLY) + return; + + /* Sort TIFFEntryOffsetAndLength array in ascending order. */ + qsort(tif->tif_dir.td_dirdatasize_offsets, + tif->tif_dir.td_dirdatasize_Noffsets, + sizeof(TIFFEntryOffsetAndLength), cmpTIFFEntryOffsetAndLength); + + /* Get offset of end of IFD entry space. */ + uint64_t IFDendoffset; + if (!(tif->tif_flags & TIFF_BIGTIFF)) + IFDendoffset = tif->tif_diroff + 2 + dircount * 12 + 4; + else + IFDendoffset = tif->tif_diroff + 8 + dircount * 20 + 8; + + /* Check which offsets are right behind IFD entries. However, LibTIFF + * increments the writing address for every external data to an even offset. + * Thus gaps of 1 byte can occur. */ + uint64_t size = 0; + uint64_t offset; + uint32_t i; + for (i = 0; i < tif->tif_dir.td_dirdatasize_Noffsets; i++) + { + offset = tif->tif_dir.td_dirdatasize_offsets[i].offset; + if (offset == IFDendoffset) + { + size += tif->tif_dir.td_dirdatasize_offsets[i].length; + IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length; + } + else if (offset == IFDendoffset + 1) + { + /* Add gap byte after previous IFD data set. */ + size += tif->tif_dir.td_dirdatasize_offsets[i].length + 1; + IFDendoffset += tif->tif_dir.td_dirdatasize_offsets[i].length; + } + else + { + /* Further data is no more continuously after IFD */ + break; + } + } + /* Check for gap byte of some easy cases. This should cover 90% of cases. + * Otherwise, IFD will be re-written even it might be safely overwritten. */ + if (tif->tif_nextdiroff != 0) + { + if (tif->tif_nextdiroff == IFDendoffset + 1) + size++; + } + else + { + /* Check for IFD data ends at EOF. Then IFD can always be safely + * overwritten. */ + offset = TIFFSeekFile(tif, 0, SEEK_END); + if (offset == IFDendoffset) + { + tif->tif_dir.td_dirdatasize_read = UINT64_MAX; + return; + } + } + + /* Finally, add the size of the IFD tag entries themselves. */ + if (!(tif->tif_flags & TIFF_BIGTIFF)) + tif->tif_dir.td_dirdatasize_read = 2 + dircount * 12 + 4 + size; + else + tif->tif_dir.td_dirdatasize_read = 8 + dircount * 20 + 8 + size; +} /*-- CalcFinalIFDdatasizeReading() --*/ + /* * Read the next TIFF directory from a file and convert it to the internal * format. We read directories sequentially. @@ -4150,7 +4281,6 @@ int TIFFReadDirectory(TIFF *tif) tif->tif_curdir = 0; else tif->tif_curdir++; - (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ TIFFReadDirectoryCheckOrder(tif, dir, dircount); @@ -4180,8 +4310,27 @@ int TIFFReadDirectory(TIFF *tif) tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS; /* free any old stuff and reinit */ + (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); + + /* After setup a fresh directory indicate that now active IFD is also + * present on file, even if its entries could not be read successfully + * below. */ + tif->tif_dir.td_iswrittentofile = TRUE; + + /* Allocate arrays for offset values outside IFD entry for IFD data size + * checking. Note: Counter are reset within TIFFFreeDirectory(). */ + tif->tif_dir.td_dirdatasize_offsets = + (TIFFEntryOffsetAndLength *)_TIFFmallocExt( + tif, dircount * sizeof(TIFFEntryOffsetAndLength)); + if (tif->tif_dir.td_dirdatasize_offsets == NULL) + { + TIFFErrorExtR( + tif, module, + "Failed to allocate memory for counting IFD data size at reading"); + goto bad; + } /* * Electronic Arts writes gray-scale TIFF files * without a PlanarConfiguration directory entry. @@ -4260,11 +4409,9 @@ int TIFFReadDirectory(TIFF *tif) dp->tdir_tag, dp->tdir_tag); /* the following knowingly leaks the anonymous field structure */ - if (!_TIFFMergeFields( - tif, - _TIFFCreateAnonField(tif, dp->tdir_tag, - (TIFFDataType)dp->tdir_type), - 1)) + const TIFFField *fld = _TIFFCreateAnonField( + tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type); + if (fld == NULL || !_TIFFMergeFields(tif, fld, 1)) { TIFFWarningExtR( tif, module, @@ -4381,6 +4528,8 @@ int TIFFReadDirectory(TIFF *tif) uint16_t value; enum TIFFReadDirEntryErr err; err = TIFFReadDirEntryShort(tif, dp, &value); + if (!EvaluateIFDdatasizeReading(tif, dp)) + goto bad; if (err == TIFFReadDirEntryErrCount) err = TIFFReadDirEntryPersampleShort(tif, dp, &value); @@ -4411,6 +4560,8 @@ int TIFFReadDirectory(TIFF *tif) err = TIFFReadDirEntryErrCount; else err = TIFFReadDirEntryDoubleArray(tif, dp, &data); + if (!EvaluateIFDdatasizeReading(tif, dp)) + goto bad; if (err != TIFFReadDirEntryErrOk) { fip = TIFFFieldWithTag(tif, dp->tdir_tag); @@ -4430,6 +4581,7 @@ int TIFFReadDirectory(TIFF *tif) break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: + { switch (dp->tdir_type) { case TIFF_SHORT: @@ -4452,9 +4604,13 @@ int TIFFReadDirectory(TIFF *tif) } _TIFFmemcpy(&(tif->tif_dir.td_stripoffset_entry), dp, sizeof(TIFFDirEntry)); - break; + if (!EvaluateIFDdatasizeReading(tif, dp)) + goto bad; + } + break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: + { switch (dp->tdir_type) { case TIFF_SHORT: @@ -4477,7 +4633,10 @@ int TIFFReadDirectory(TIFF *tif) } _TIFFmemcpy(&(tif->tif_dir.td_stripbytecount_entry), dp, sizeof(TIFFDirEntry)); - break; + if (!EvaluateIFDdatasizeReading(tif, dp)) + goto bad; + } + break; case TIFFTAG_COLORMAP: case TIFFTAG_TRANSFERFUNCTION: { @@ -4531,6 +4690,8 @@ int TIFFReadDirectory(TIFF *tif) err = TIFFReadDirEntryErrCount; else err = TIFFReadDirEntryShortArray(tif, dp, &value); + if (!EvaluateIFDdatasizeReading(tif, dp)) + goto bad; if (err != TIFFReadDirEntryErrOk) { fip = TIFFFieldWithTag(tif, dp->tdir_tag); @@ -4621,9 +4782,12 @@ int TIFFReadDirectory(TIFF *tif) default: (void)TIFFFetchNormalTag(tif, dp, TRUE); break; - } - } /* -- if (!dp->tdir_ignore) */ - } /* -- for-loop -- */ + } /* -- switch (dp->tdir_tag) -- */ + } /* -- if (!dp->tdir_ignore) */ + } /* -- for-loop -- */ + + /* Evaluate final IFD data size. */ + CalcFinalIFDdatasizeReading(tif, dircount); /* * OJPEG hack: @@ -5032,7 +5196,7 @@ bad: if (dir) _TIFFfreeExt(tif, dir); return (0); -} +} /*-- TIFFReadDirectory() --*/ static void TIFFReadDirectoryCheckOrder(TIFF *tif, TIFFDirEntry *dir, uint16_t dircount) @@ -5116,8 +5280,7 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff, uint16_t di; const TIFFField *fip; uint32_t fii; - (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ - _TIFFSetupFields(tif, infoarray); + dircount = TIFFFetchDirectory(tif, diroff, &dir, NULL); if (!dircount) { @@ -5126,9 +5289,56 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff, diroff); return 0; } - TIFFFreeDirectory(tif); - _TIFFmemset(&tif->tif_dir, 0, sizeof(TIFFDirectory)); TIFFReadDirectoryCheckOrder(tif, dir, dircount); + + /* + * Mark duplicates of any tag to be ignored (bugzilla 1994) + * to avoid certain pathological problems. + */ + { + TIFFDirEntry *ma; + uint16_t mb; + for (ma = dir, mb = 0; mb < dircount; ma++, mb++) + { + TIFFDirEntry *na; + uint16_t nb; + for (na = ma + 1, nb = mb + 1; nb < dircount; na++, nb++) + { + if (ma->tdir_tag == na->tdir_tag) + { + na->tdir_ignore = TRUE; + } + } + } + } + + /* Free any old stuff and reinit. */ + (*tif->tif_cleanup)(tif); /* cleanup any previous compression state */ + TIFFFreeDirectory(tif); + /* Even if custom directories do not need the default settings of a standard + * IFD, the pointer to the TIFFSetField() and TIFFGetField() (i.e. + * tif->tif_tagmethods.vsetfield and tif->tif_tagmethods.vgetfield) need to + * be initialized, which is done in TIFFDefaultDirectory(). + * After that, the field array for the custom tags needs to be setup again. + */ + TIFFDefaultDirectory(tif); + _TIFFSetupFields(tif, infoarray); + + /* Allocate arrays for offset values outside IFD entry for IFD data size + * checking. Note: Counter are reset within TIFFFreeDirectory(). */ + tif->tif_dir.td_dirdatasize_offsets = + (TIFFEntryOffsetAndLength *)_TIFFmallocExt( + tif, dircount * sizeof(TIFFEntryOffsetAndLength)); + if (tif->tif_dir.td_dirdatasize_offsets == NULL) + { + TIFFErrorExtR( + tif, module, + "Failed to allocate memory for counting IFD data size at reading"); + if (dir) + _TIFFfreeExt(tif, dir); + return 0; + } + for (di = 0, dp = dir; di < dircount; di++, dp++) { TIFFReadDirectoryFindFieldInfo(tif, dp->tdir_tag, &fii); @@ -5138,11 +5348,9 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff, "Unknown field with tag %" PRIu16 " (0x%" PRIx16 ") encountered", dp->tdir_tag, dp->tdir_tag); - if (!_TIFFMergeFields( - tif, - _TIFFCreateAnonField(tif, dp->tdir_tag, - (TIFFDataType)dp->tdir_type), - 1)) + const TIFFField *fld = _TIFFCreateAnonField( + tif, dp->tdir_tag, (TIFFDataType)dp->tdir_type); + if (fld == NULL || !_TIFFMergeFields(tif, fld, 1)) { TIFFWarningExtR(tif, module, "Registering anonymous field with tag %" PRIu16 @@ -5225,6 +5433,9 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff, } /*-- if (!dp->tdir_ignore) */ } } + /* Evaluate final IFD data size. */ + CalcFinalIFDdatasizeReading(tif, dircount); + /* To be able to return from SubIFD or custom-IFD to main-IFD */ tif->tif_setdirectory_force_absolute = TRUE; if (dir) @@ -5238,9 +5449,7 @@ int TIFFReadCustomDirectory(TIFF *tif, toff_t diroff, */ int TIFFReadEXIFDirectory(TIFF *tif, toff_t diroff) { - const TIFFFieldArray *exifFieldArray; - exifFieldArray = _TIFFGetExifFields(); - return TIFFReadCustomDirectory(tif, diroff, exifFieldArray); + return TIFFReadCustomDirectory(tif, diroff, _TIFFGetExifFields()); } /* @@ -5248,9 +5457,7 @@ int TIFFReadEXIFDirectory(TIFF *tif, toff_t diroff) */ int TIFFReadGPSDirectory(TIFF *tif, toff_t diroff) { - const TIFFFieldArray *gpsFieldArray; - gpsFieldArray = _TIFFGetGpsFields(); - return TIFFReadCustomDirectory(tif, diroff, gpsFieldArray); + return TIFFReadCustomDirectory(tif, diroff, _TIFFGetGpsFields()); } static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir, @@ -5266,6 +5473,24 @@ static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir, if (!_TIFFFillStrilesInternal(tif, 0)) return -1; + const uint64_t allocsize = (uint64_t)td->td_nstrips * sizeof(uint64_t); + uint64_t filesize = 0; + if (allocsize > 100 * 1024 * 1024) + { + /* Before allocating a huge amount of memory for corrupted files, check + * if size of requested memory is not greater than file size. */ + filesize = TIFFGetFileSize(tif); + if (allocsize > filesize) + { + TIFFWarningExtR( + tif, module, + "Requested memory size for StripByteCounts of %" PRIu64 + " is greater than filesize %" PRIu64 ". Memory not allocated", + allocsize, filesize); + return -1; + } + } + if (td->td_stripbytecount_p) _TIFFfreeExt(tif, td->td_stripbytecount_p); td->td_stripbytecount_p = (uint64_t *)_TIFFCheckMalloc( @@ -5276,9 +5501,7 @@ static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir, if (td->td_compression != COMPRESSION_NONE) { uint64_t space; - uint64_t filesize; uint16_t n; - filesize = TIFFGetFileSize(tif); if (!(tif->tif_flags & TIFF_BIGTIFF)) space = sizeof(TIFFHeaderClassic) + 2 + dircount * 12 + 4; else @@ -5314,6 +5537,8 @@ static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir, return -1; space += datasize; } + if (filesize == 0) + filesize = TIFFGetFileSize(tif); if (filesize < space) /* we should perhaps return in error ? */ space = filesize; @@ -5921,6 +6146,20 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff, "directories not supported"); return 0; } + /* Before allocating a huge amount of memory for corrupted files, check + * if size of requested memory is not greater than file size. */ + uint64_t filesize = TIFFGetFileSize(tif); + uint64_t allocsize = (uint64_t)dircount16 * dirsize; + if (allocsize > filesize) + { + TIFFWarningExtR( + tif, module, + "Requested memory size for TIFF directory of %" PRIu64 + " is greater than filesize %" PRIu64 + ". Memory not allocated, TIFF directory not read", + allocsize, filesize); + return 0; + } origdir = _TIFFCheckMalloc(tif, dircount16, dirsize, "to read TIFF directory"); if (origdir == NULL) @@ -5968,6 +6207,8 @@ static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff, } } } + /* No check against filesize needed here because "dir" should have same size + * than "origdir" checked above. */ dir = (TIFFDirEntry *)_TIFFCheckMalloc( tif, dircount16, sizeof(TIFFDirEntry), "to read TIFF directory"); if (dir == 0) @@ -6080,6 +6321,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) } } } + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != NULL) + _TIFFfreeExt(tif, data); + return (0); + } if (mb + 1 < (uint32_t)dp->tdir_count) TIFFWarningExtR( tif, module, @@ -6089,15 +6336,15 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) fip->field_name); else if (mb + 1 > (uint32_t)dp->tdir_count) { - uint8_t *o; - TIFFWarningExtR( - tif, module, - "ASCII value for tag \"%s\" does not end in null byte", - fip->field_name); + TIFFWarningExtR(tif, module, + "ASCII value for tag \"%s\" does not end " + "in null byte. Forcing it to be null", + fip->field_name); /* TIFFReadDirEntryArrayWithLimit() ensures this can't be * larger than MAX_SIZE_TAG_DATA */ assert((uint32_t)dp->tdir_count + 1 == dp->tdir_count + 1); - o = _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); + uint8_t *o = + _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); if (o == NULL) { if (data != NULL) @@ -6207,6 +6454,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLong8(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + return 0; if (!TIFFSetField(tif, dp->tdir_tag, data)) return (0); } @@ -6220,6 +6469,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlong8(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + return 0; if (!TIFFSetField(tif, dp->tdir_tag, data)) return (0); } @@ -6233,6 +6484,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryFloat(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + return 0; if (!TIFFSetField(tif, dp->tdir_tag, data)) return (0); } @@ -6246,6 +6499,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryDouble(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + return 0; if (!TIFFSetField(tif, dp->tdir_tag, data)) return (0); } @@ -6259,6 +6514,8 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryIfd8(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + return 0; if (!TIFFSetField(tif, dp->tdir_tag, data)) return (0); } @@ -6308,6 +6565,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryByteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6337,6 +6600,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySbyteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6366,6 +6635,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryShortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6395,6 +6670,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySshortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6424,6 +6705,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6453,6 +6740,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6482,6 +6775,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6511,6 +6810,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6540,6 +6845,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryFloatArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6571,6 +6882,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryDoubleArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, data); if (data != 0) @@ -6593,16 +6910,39 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryByteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; if (data != 0 && dp->tdir_count > 0 && data[dp->tdir_count - 1] != '\0') { - TIFFWarningExtR( - tif, module, - "ASCII value for tag \"%s\" does not end in null " - "byte. Forcing it to be null", - fip->field_name); - data[dp->tdir_count - 1] = '\0'; + TIFFWarningExtR(tif, module, + "ASCII value for ASCII array tag " + "\"%s\" does not end in null " + "byte. Forcing it to be null", + fip->field_name); + /* Enlarge buffer and add terminating null. */ + uint8_t *o = + _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); + if (o == NULL) + { + if (data != NULL) + _TIFFfreeExt(tif, data); + return (0); + } + if (dp->tdir_count > 0) + { + _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count); + } + o[(uint32_t)dp->tdir_count] = 0; + dp->tdir_count++; /* Increment for added null. */ + if (data != 0) + _TIFFfreeExt(tif, data); + data = o; } m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6626,6 +6966,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryByteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6649,6 +6995,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySbyteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6672,6 +7024,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryShortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6695,6 +7053,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySshortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6718,6 +7082,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6741,6 +7111,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6764,6 +7140,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6787,6 +7169,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6810,6 +7198,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryFloatArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6833,6 +7227,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryDoubleArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6856,6 +7256,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryIfd8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint16_t)(dp->tdir_count), data); @@ -6875,15 +7281,39 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryByteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; if (data != 0 && dp->tdir_count > 0 && data[dp->tdir_count - 1] != '\0') { - TIFFWarningExtR(tif, module, - "ASCII value for tag \"%s\" does not end " - "in null byte. Forcing it to be null", - fip->field_name); - data[dp->tdir_count - 1] = '\0'; + TIFFWarningExtR( + tif, module, + "ASCII value for ASCII array tag \"%s\" does not end " + "in null byte. Forcing it to be null", + fip->field_name); + /* Enlarge buffer and add terminating null. */ + uint8_t *o = + _TIFFmallocExt(tif, (uint32_t)dp->tdir_count + 1); + if (o == NULL) + { + if (data != NULL) + _TIFFfreeExt(tif, data); + return (0); + } + if (dp->tdir_count > 0) + { + _TIFFmemcpy(o, data, (uint32_t)dp->tdir_count); + } + o[(uint32_t)dp->tdir_count] = 0; + dp->tdir_count++; /* Increment for added null. */ + if (data != 0) + _TIFFfreeExt(tif, data); + data = o; } m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -6927,6 +7357,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) } if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, count, data); if (data != 0) @@ -6944,6 +7380,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySbyteArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -6962,6 +7404,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryShortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -6980,6 +7428,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySshortArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -6998,6 +7452,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7016,6 +7476,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlongArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7034,6 +7500,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryLong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7052,6 +7524,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntrySlong8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7070,6 +7548,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryFloatArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7088,6 +7572,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryDoubleArray(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7106,6 +7596,12 @@ static int TIFFFetchNormalTag(TIFF *tif, TIFFDirEntry *dp, int recover) err = TIFFReadDirEntryIfd8Array(tif, dp, &data); if (err == TIFFReadDirEntryErrOk) { + if (!EvaluateIFDdatasizeReading(tif, dp)) + { + if (data != 0) + _TIFFfreeExt(tif, data); + return 0; + } int m; m = TIFFSetField(tif, dp->tdir_tag, (uint32_t)(dp->tdir_count), data); @@ -7164,6 +7660,25 @@ static int TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir, uint32_t nstrips, return (0); } + const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t); + if (allocsize > 100 * 1024 * 1024) + { + /* Before allocating a huge amount of memory for corrupted files, + * check if size of requested memory is not greater than file size. + */ + const uint64_t filesize = TIFFGetFileSize(tif); + if (allocsize > filesize) + { + TIFFWarningExtR( + tif, module, + "Requested memory size for StripArray of %" PRIu64 + " is greater than filesize %" PRIu64 + ". Memory not allocated", + allocsize, filesize); + _TIFFfreeExt(tif, data); + return (0); + } + } resizeddata = (uint64_t *)_TIFFCheckMalloc( tif, nstrips, sizeof(uint64_t), "for strip array"); if (resizeddata == 0) @@ -7263,6 +7778,26 @@ static void allocChoppedUpStripArrays(TIFF *tif, uint32_t nstrips, } bytecount = last_offset + last_bytecount - offset; + /* Before allocating a huge amount of memory for corrupted files, check if + * size of StripByteCount and StripOffset tags is not greater than + * file size. + */ + const uint64_t allocsize = (uint64_t)nstrips * sizeof(uint64_t) * 2; + if (allocsize > 100 * 1024 * 1024) + { + const uint64_t filesize = TIFFGetFileSize(tif); + if (allocsize > filesize) + { + TIFFWarningExtR(tif, "allocChoppedUpStripArrays", + "Requested memory size for StripByteCount and " + "StripOffsets %" PRIu64 + " is greater than filesize %" PRIu64 + ". Memory not allocated", + allocsize, filesize); + return; + } + } + newcounts = (uint64_t *)_TIFFCheckMalloc(tif, nstrips, sizeof(uint64_t), "for chopped \"StripByteCounts\" array"); @@ -7363,7 +7898,7 @@ static void ChopUpSingleUncompressedStrip(TIFF *tif) /* * never increase the number of rows per strip */ - if (rowsperstrip >= td->td_rowsperstrip) + if (rowsperstrip >= td->td_rowsperstrip || rowsperstrip == 0) return; nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); if (nstrips == 0) @@ -7459,6 +7994,8 @@ static void TryChopUpUncompressedBigTiff(TIFF *tif) stripbytes = rowblocksperstrip * rowblockbytes; assert(stripbytes <= 0x7FFFFFFFUL); + if (rowsperstrip == 0) + return; nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); if (nstrips == 0) return; diff --git a/3rdparty/libtiff/tif_dirwrite.c b/3rdparty/libtiff/tif_dirwrite.c index d8844bbd8a..facdeaf7b1 100644 --- a/3rdparty/libtiff/tif_dirwrite.c +++ b/3rdparty/libtiff/tif_dirwrite.c @@ -303,12 +303,14 @@ int TIFFWriteCustomDirectory(TIFF *tif, uint64_t *pdiroff) } /* - * Similar to TIFFWriteDirectory(), but if the directory has already + * Similar to TIFFWriteDirectorySec(), but if the directory has already * been written once, it is relocated to the end of the file, in case it * has changed in size. Note that this will result in the loss of the * previously used directory space. */ -int TIFFRewriteDirectory(TIFF *tif) + +static int TIFFRewriteDirectorySec(TIFF *tif, int isimage, int imagedone, + uint64_t *pdiroff) { static const char module[] = "TIFFRewriteDirectory"; @@ -464,10 +466,20 @@ int TIFFRewriteDirectory(TIFF *tif) } /* - * Now use TIFFWriteDirectory() normally. + * Now use TIFFWriteDirectorySec() normally. */ + return TIFFWriteDirectorySec(tif, isimage, imagedone, pdiroff); +} /*-- TIFFRewriteDirectorySec() --*/ - return TIFFWriteDirectory(tif); +/* + * Similar to TIFFWriteDirectory(), but if the directory has already + * been written once, it is relocated to the end of the file, in case it + * has changed in size. Note that this will result in the loss of the + * previously used directory space. + */ +int TIFFRewriteDirectory(TIFF *tif) +{ + return TIFFRewriteDirectorySec(tif, TRUE, TRUE, NULL); } static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, @@ -542,7 +554,12 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, dirsize = 0; while (1) { + /* The first loop only determines "ndir" and uses TIFFLinkDirectory() to + * set the offset at which the IFD is to be written to the file. + * The second loop writes IFD entries to the file. */ ndir = 0; + if (dir == NULL) + tif->tif_dir.td_dirdatasize_write = 0; if (isimage) { if (TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) @@ -852,7 +869,7 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, if ((o->field_bit >= FIELD_CODEC) && (TIFFFieldSet(tif, o->field_bit))) { - switch (o->get_field_type) + switch (o->set_field_type) { case TIFF_SETGET_ASCII: { @@ -1085,8 +1102,18 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, break; } } + /* "break" if IFD has been written above in second pass.*/ if (dir != NULL) break; + + /* Evaluate IFD data size: Finally, add the size of the IFD tag entries + * themselves. */ + if (!(tif->tif_flags & TIFF_BIGTIFF)) + tif->tif_dir.td_dirdatasize_write += 2 + ndir * 12 + 4; + else + tif->tif_dir.td_dirdatasize_write += 8 + ndir * 20 + 8; + + /* Setup a new directory within first pass. */ dir = _TIFFmallocExt(tif, ndir * sizeof(TIFFDirEntry)); if (dir == NULL) { @@ -1095,18 +1122,58 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, } if (isimage) { - if ((tif->tif_diroff == 0) && (!TIFFLinkDirectory(tif))) - goto bad; + /* Check, weather the IFD to be written is new or an already written + * IFD can be overwritten or needs to be re-written to a different + * location in the file because the IFD is extended with additional + * tags or the IFD data size is increased. + * - tif_diroff == 0, if a new directory has to be linked. + * - tif_diroff != 0, IFD has been re-read from file and will be + * overwritten or re-written. + */ + if (tif->tif_diroff == 0) + { + if (!TIFFLinkDirectory(tif)) + goto bad; + } + else if (tif->tif_dir.td_dirdatasize_write > + tif->tif_dir.td_dirdatasize_read) + { + if (dir != NULL) + { + _TIFFfreeExt(tif, dir); + dir = NULL; + } + if (!TIFFRewriteDirectorySec(tif, isimage, imagedone, pdiroff)) + goto bad; + return (1); + } } else - tif->tif_diroff = - (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1)); + { + /* For !isimage, which means custom-IFD like EXIFIFD or + * checkpointing an IFD, determine whether to overwrite or append at + * the end of the file. + */ + if (!((tif->tif_dir.td_dirdatasize_read > 0) && + (tif->tif_dir.td_dirdatasize_write <= + tif->tif_dir.td_dirdatasize_read))) + { + /* Append at end of file and increment to an even offset. */ + tif->tif_diroff = + (TIFFSeekFile(tif, 0, SEEK_END) + 1) & (~((toff_t)1)); + } + } + /* Return IFD offset */ if (pdiroff != NULL) *pdiroff = tif->tif_diroff; if (!(tif->tif_flags & TIFF_BIGTIFF)) dirsize = 2 + ndir * 12 + 4; else dirsize = 8 + ndir * 20 + 8; + /* Append IFD data stright after the IFD tag entries. + * Data that does not fit into an IFD tag entry is written to the file + * in the second pass of the while loop. That offset is stored in "dir". + */ tif->tif_dataoff = tif->tif_diroff + dirsize; if (!(tif->tif_flags & TIFF_BIGTIFF)) tif->tif_dataoff = (uint32_t)tif->tif_dataoff; @@ -1118,16 +1185,12 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, } if (tif->tif_dataoff & 1) tif->tif_dataoff++; - if (isimage) - { - if (tif->tif_curdir == TIFF_NON_EXISTENT_DIR_NUMBER) - tif->tif_curdir = 0; - else - tif->tif_curdir++; - } - } + } /* while() */ if (isimage) { + /* For SubIFDs remember offset of SubIFD tag within main IFD. + * However, might be already done in TIFFWriteDirectoryTagSubifd() if + * there are more than one SubIFD. */ if (TIFFFieldSet(tif, FIELD_SUBIFD) && (tif->tif_subifdoff == 0)) { uint32_t na; @@ -1148,6 +1211,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, tif->tif_subifdoff = tif->tif_diroff + 8 + na * 20 + 12; } } + /* Copy/swab IFD entries from "dir" into "dirmem", + * which is then written to file. */ dirmem = _TIFFmallocExt(tif, dirsize); if (dirmem == NULL) { @@ -1227,7 +1292,8 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, dir = NULL; if (!SeekOK(tif, tif->tif_diroff)) { - TIFFErrorExtR(tif, module, "IO error writing directory"); + TIFFErrorExtR(tif, module, + "IO error writing directory at seek to offset"); goto bad; } if (!WriteOK(tif, dirmem, (tmsize_t)dirsize)) @@ -1236,18 +1302,83 @@ static int TIFFWriteDirectorySec(TIFF *tif, int isimage, int imagedone, goto bad; } _TIFFfreeExt(tif, dirmem); + + /* Increment tif_curdir if IFD wasn't already written to file and no error + * occurred during IFD writing above. */ + if (isimage && !tif->tif_dir.td_iswrittentofile) + { + if (!((tif->tif_flags & TIFF_INSUBIFD) && + !(TIFFFieldSet(tif, FIELD_SUBIFD)))) + { + /*-- Normal main-IFD case --*/ + if (tif->tif_curdircount != TIFF_NON_EXISTENT_DIR_NUMBER) + { + tif->tif_curdir = tif->tif_curdircount; + } + else + { + /*ToDo SU: NEW_IFD_CURDIR_INCREMENTING: Delete this + * unexpected case after some testing time. */ + /* Attention: tif->tif_curdircount is already set within + * TIFFNumberOfDirectories() */ + tif->tif_curdircount = TIFFNumberOfDirectories(tif); + tif->tif_curdir = tif->tif_curdircount; + TIFFErrorExtR( + tif, module, + "tif_curdircount is TIFF_NON_EXISTENT_DIR_NUMBER, " + "not expected !! Line %d", + __LINE__); + goto bad; + } + } + else + { + /*-- SubIFD case -- */ + /* tif_curdir is always set to 0 for all SubIFDs. */ + tif->tif_curdir = 0; + } + } + /* Increment tif_curdircount only if main-IFD of an image was not already + * present on file. */ + /* Check in combination with (... && !(TIFFFieldSet(tif, FIELD_SUBIFD))) + * is necessary here because TIFF_INSUBIFD was already set above for the + * next SubIFD when this main-IFD (with FIELD_SUBIFD) is currently being + * written. */ + if (isimage && !tif->tif_dir.td_iswrittentofile && + !((tif->tif_flags & TIFF_INSUBIFD) && + !(TIFFFieldSet(tif, FIELD_SUBIFD)))) + tif->tif_curdircount++; + + tif->tif_dir.td_iswrittentofile = TRUE; + + /* Reset SubIFD writing stage after last SubIFD has been written. */ + if (imagedone && (tif->tif_flags & TIFF_INSUBIFD) && tif->tif_nsubifd == 0) + tif->tif_flags &= ~TIFF_INSUBIFD; + + /* Add or update this directory to the IFD list. */ + if (!_TIFFCheckDirNumberAndOffset(tif, tif->tif_curdir, tif->tif_diroff)) + { + TIFFErrorExtR(tif, module, + "Starting directory %u at offset 0x%" PRIx64 " (%" PRIu64 + ") might cause an IFD loop", + tif->tif_curdir, tif->tif_diroff, tif->tif_diroff); + } + if (imagedone) { TIFFFreeDirectory(tif); tif->tif_flags &= ~TIFF_DIRTYDIRECT; tif->tif_flags &= ~TIFF_DIRTYSTRIP; (*tif->tif_cleanup)(tif); - /* - * Reset directory-related state for subsequent - * directories. - */ + /* Reset directory-related state for subsequent directories. */ TIFFCreateDirectory(tif); } + else + { + /* IFD is only checkpointed to file (or a custom IFD like EXIF is + * written), thus set IFD data size written to file. */ + tif->tif_dir.td_dirdatasize_read = tif->tif_dir.td_dirdatasize_write; + } return (1); bad: if (dir != NULL) @@ -1401,11 +1532,6 @@ static int TIFFWriteDirectoryTagAscii(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, char *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return ( TIFFWriteDirectoryTagCheckedAscii(tif, ndir, dir, tag, count, value)); } @@ -1414,11 +1540,6 @@ static int TIFFWriteDirectoryTagUndefinedArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, uint8_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedUndefinedArray(tif, ndir, dir, tag, count, value)); } @@ -1427,11 +1548,6 @@ static int TIFFWriteDirectoryTagByteArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, uint8_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedByteArray(tif, ndir, dir, tag, count, value)); } @@ -1440,11 +1556,6 @@ static int TIFFWriteDirectoryTagSbyteArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, int8_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedSbyteArray(tif, ndir, dir, tag, count, value)); } @@ -1453,11 +1564,6 @@ static int TIFFWriteDirectoryTagShort(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint16_t value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag, value)); } @@ -1465,11 +1571,6 @@ static int TIFFWriteDirectoryTagShortArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, uint16_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedShortArray(tif, ndir, dir, tag, count, value)); } @@ -1485,8 +1586,9 @@ static int TIFFWriteDirectoryTagShortPerSample(TIFF *tif, uint32_t *ndir, int o; if (dir == NULL) { - (*ndir)++; - return (1); + /* only evaluate IFD data size and inc. ndir */ + return (TIFFWriteDirectoryTagCheckedShortArray( + tif, ndir, dir, tag, tif->tif_dir.td_samplesperpixel, NULL)); } m = _TIFFmallocExt(tif, tif->tif_dir.td_samplesperpixel * sizeof(uint16_t)); if (m == NULL) @@ -1506,11 +1608,6 @@ static int TIFFWriteDirectoryTagSshortArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, int16_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedSshortArray(tif, ndir, dir, tag, count, value)); } @@ -1519,11 +1616,6 @@ static int TIFFWriteDirectoryTagLong(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedLong(tif, ndir, dir, tag, value)); } @@ -1531,11 +1623,6 @@ static int TIFFWriteDirectoryTagLongArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, uint32_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedLongArray(tif, ndir, dir, tag, count, value)); } @@ -1544,11 +1631,6 @@ static int TIFFWriteDirectoryTagSlongArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, int32_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedSlongArray(tif, ndir, dir, tag, count, value)); } @@ -1572,8 +1654,9 @@ static int TIFFWriteDirectoryTagLong8Array(TIFF *tif, uint32_t *ndir, /* is this just a counting pass? */ if (dir == NULL) { - (*ndir)++; - return (1); + /* only evaluate IFD data size and inc. ndir */ + return (TIFFWriteDirectoryTagCheckedLong8Array(tif, ndir, dir, tag, + count, value)); } /* We always write Long8 for BigTIFF, no checking needed. */ @@ -1632,8 +1715,9 @@ static int TIFFWriteDirectoryTagSlong8Array(TIFF *tif, uint32_t *ndir, /* is this just a counting pass? */ if (dir == NULL) { - (*ndir)++; - return (1); + /* only evaluate IFD data size and inc. ndir */ + return (TIFFWriteDirectoryTagCheckedSlong8Array(tif, ndir, dir, tag, + count, value)); } /* We always write SLong8 for BigTIFF, no checking needed. */ if (tif->tif_flags & TIFF_BIGTIFF) @@ -1686,11 +1770,6 @@ static int TIFFWriteDirectoryTagRational(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, double value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedRational(tif, ndir, dir, tag, value)); } @@ -1698,11 +1777,6 @@ static int TIFFWriteDirectoryTagRationalArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, float *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedRationalArray(tif, ndir, dir, tag, count, value)); } @@ -1711,11 +1785,6 @@ static int TIFFWriteDirectoryTagSrationalArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, float *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedSrationalArray(tif, ndir, dir, tag, count, value)); } @@ -1727,11 +1796,6 @@ static int TIFFWriteDirectoryTagRationalDoubleArray(TIFF *tif, uint32_t *ndir, uint32_t count, double *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedRationalDoubleArray(tif, ndir, dir, tag, count, value)); } @@ -1742,11 +1806,6 @@ static int TIFFWriteDirectoryTagSrationalDoubleArray(TIFF *tif, uint32_t *ndir, uint32_t count, double *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedSrationalDoubleArray( tif, ndir, dir, tag, count, value)); } @@ -1755,11 +1814,6 @@ static int TIFFWriteDirectoryTagFloatArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, float *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedFloatArray(tif, ndir, dir, tag, count, value)); } @@ -1768,11 +1822,6 @@ static int TIFFWriteDirectoryTagDoubleArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, double *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedDoubleArray(tif, ndir, dir, tag, count, value)); } @@ -1781,11 +1830,6 @@ static int TIFFWriteDirectoryTagIfdArray(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t count, uint32_t *value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } return (TIFFWriteDirectoryTagCheckedIfdArray(tif, ndir, dir, tag, count, value)); } @@ -1794,11 +1838,6 @@ static int TIFFWriteDirectoryTagShortLong(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir, uint16_t tag, uint32_t value) { - if (dir == NULL) - { - (*ndir)++; - return (1); - } if (value <= 0xFFFF) return (TIFFWriteDirectoryTagCheckedShort(tif, ndir, dir, tag, (uint16_t)value)); @@ -1824,7 +1863,7 @@ static int _WriteAsType(TIFF *tif, uint64_t strile_size, compression == COMPRESSION_WEBP || compression == COMPRESSION_JXL) { /* For a few select compression types, we assume that in the worst */ - /* case the compressed size will be 10 times the uncompressed size */ + /* case the compressed size will be 10 times the uncompressed size. */ /* This is overly pessismistic ! */ return strile_size >= uncompressed_threshold / 10; } @@ -1856,15 +1895,16 @@ static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir, int o; int write_aslong4; - /* is this just a counting pass? */ - if (dir == NULL) - { - (*ndir)++; - return (1); - } - if (tif->tif_dir.td_deferstrilearraywriting) { + if (dir == NULL) + { + /* This is just a counting pass to count IFD entries. + * For deferstrilearraywriting no extra bytes will be written + * into IFD space. */ + (*ndir)++; + return 1; + } return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL); } @@ -1872,12 +1912,10 @@ static int TIFFWriteDirectoryTagLongLong8Array(TIFF *tif, uint32_t *ndir, if (tif->tif_flags & TIFF_BIGTIFF) { int write_aslong8 = 1; - /* In the case of ByteCounts array, we may be able to write them on */ - /* LONG if the strip/tilesize is not too big. */ - /* Also do that for count > 1 in the case someone would want to create - */ - /* a single-strip file with a growing height, in which case using */ - /* LONG8 will be safer. */ + /* In the case of ByteCounts array, we may be able to write them on LONG + * if the strip/tilesize is not too big. Also do that for count > 1 in + * the case someone would want to create a single-strip file with a + * growing height, in which case using LONG8 will be safer. */ if (count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS) { write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif)); @@ -1989,13 +2027,6 @@ static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir, uint32_t *q; int o; - /* is this just a counting pass? */ - if (dir == NULL) - { - (*ndir)++; - return (1); - } - /* We always write IFD8 for BigTIFF, no checking needed. */ if (tif->tif_flags & TIFF_BIGTIFF) return TIFFWriteDirectoryTagCheckedIfd8Array(tif, ndir, dir, tag, count, @@ -2032,6 +2063,26 @@ static int TIFFWriteDirectoryTagIfdIfd8Array(TIFF *tif, uint32_t *ndir, return (o); } +/* + * Auxiliary function to determine the IFD data size to be written to the file. + * The IFD data size is finally the size of the IFD tag entries plus the IFD + * data that is written directly after the IFD tag entries. + */ +static void EvaluateIFDdatasizeWrite(TIFF *tif, uint32_t count, + uint32_t typesize, uint32_t *ndir) +{ + uint64_t datalength = (uint64_t)count * typesize; + if (datalength > ((tif->tif_flags & TIFF_BIGTIFF) ? 0x8U : 0x4U)) + { + /* LibTIFF increments write address to an even offset, thus datalength + * written is also incremented. */ + if (datalength & 1) + datalength++; + tif->tif_dir.td_dirdatasize_write += datalength; + } + (*ndir)++; +} + static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir, TIFFDirEntry *dir) { @@ -2039,12 +2090,13 @@ static int TIFFWriteDirectoryTagColormap(TIFF *tif, uint32_t *ndir, uint32_t m; uint16_t *n; int o; - if (dir == NULL) - { - (*ndir)++; - return (1); - } m = (1 << tif->tif_dir.td_bitspersample); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, 3 * m, sizeof(uint16_t), ndir); + return 1; + } + n = _TIFFmallocExt(tif, 3 * m * sizeof(uint16_t)); if (n == NULL) { @@ -2068,11 +2120,6 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, uint16_t n; uint16_t *o; int p; - if (dir == NULL) - { - (*ndir)++; - return (1); - } /* TIFFTAG_TRANSFERFUNCTION expects (1 or 3) pointer to arrays with * (1 << BitsPerSample) * uint16_t values. */ @@ -2086,9 +2133,9 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, { if (tif->tif_dir.td_transferfunction[i] == NULL) { - TIFFWarningExtR( - tif, module, - "Too few TransferFunctions provided. Tag not written to file"); + TIFFWarningExtR(tif, module, + "Too few TransferFunctions provided. Tag " + "not written to file"); return (1); /* Not an error; only tag is not written. */ } } @@ -2108,6 +2155,12 @@ static int TIFFWriteDirectoryTagTransferfunction(TIFF *tif, uint32_t *ndir, m * sizeof(uint16_t))) n = 1; } + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, n * m, 2, ndir); + return 1; + } + o = _TIFFmallocExt(tif, n * m * sizeof(uint16_t)); if (o == NULL) { @@ -2136,11 +2189,6 @@ static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir, int n; if (tif->tif_dir.td_nsubifd == 0) return (1); - if (dir == NULL) - { - (*ndir)++; - return (1); - } m = tif->tif_dataoff; if (!(tif->tif_flags & TIFF_BIGTIFF)) { @@ -2178,6 +2226,12 @@ static int TIFFWriteDirectoryTagSubifd(TIFF *tif, uint32_t *ndir, n = TIFFWriteDirectoryTagCheckedIfd8Array( tif, ndir, dir, TIFFTAG_SUBIFD, tif->tif_dir.td_nsubifd, tif->tif_dir.td_subifd); + + if (dir == NULL) + /* Just have evaluated IFD data size and incremented ndir + * above in sub-functions. */ + return (n); + if (!n) return (0); /* @@ -2202,6 +2256,11 @@ static int TIFFWriteDirectoryTagCheckedAscii(TIFF *tif, uint32_t *ndir, uint32_t count, char *value) { assert(sizeof(char) == 1); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 1, ndir); + return 1; + } return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_ASCII, count, count, value)); } @@ -2213,6 +2272,11 @@ static int TIFFWriteDirectoryTagCheckedUndefinedArray(TIFF *tif, uint32_t *ndir, uint8_t *value) { assert(sizeof(uint8_t) == 1); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 1, ndir); + return 1; + } return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_UNDEFINED, count, count, value)); } @@ -2223,6 +2287,11 @@ static int TIFFWriteDirectoryTagCheckedByteArray(TIFF *tif, uint32_t *ndir, uint8_t *value) { assert(sizeof(uint8_t) == 1); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 1, ndir); + return 1; + } return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_BYTE, count, count, value)); } @@ -2233,6 +2302,11 @@ static int TIFFWriteDirectoryTagCheckedSbyteArray(TIFF *tif, uint32_t *ndir, int8_t *value) { assert(sizeof(int8_t) == 1); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 1, ndir); + return 1; + } return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SBYTE, count, count, value)); } @@ -2243,6 +2317,12 @@ static int TIFFWriteDirectoryTagCheckedShort(TIFF *tif, uint32_t *ndir, { uint16_t m; assert(sizeof(uint16_t) == 2); + if (dir == NULL) + { + /* No additional data to IFD data size just increment ndir. */ + (*ndir)++; + return 1; + } m = value; if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&m); @@ -2257,6 +2337,11 @@ static int TIFFWriteDirectoryTagCheckedShortArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x80000000); assert(sizeof(uint16_t) == 2); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 2, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfShort(value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SHORT, count, @@ -2270,6 +2355,11 @@ static int TIFFWriteDirectoryTagCheckedSshortArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x80000000); assert(sizeof(int16_t) == 2); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 2, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfShort((uint16_t *)value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SSHORT, count, @@ -2282,6 +2372,12 @@ static int TIFFWriteDirectoryTagCheckedLong(TIFF *tif, uint32_t *ndir, { uint32_t m; assert(sizeof(uint32_t) == 4); + if (dir == NULL) + { + /* No additional data to IFD data size just increment ndir. */ + (*ndir)++; + return 1; + } m = value; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&m); @@ -2296,6 +2392,11 @@ static int TIFFWriteDirectoryTagCheckedLongArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x40000000); assert(sizeof(uint32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 4, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong(value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG, count, @@ -2309,6 +2410,11 @@ static int TIFFWriteDirectoryTagCheckedSlongArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x40000000); assert(sizeof(int32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 4, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong((uint32_t *)value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG, count, @@ -2328,6 +2434,11 @@ static int TIFFWriteDirectoryTagCheckedLong8Array(TIFF *tif, uint32_t *ndir, "LONG8 not allowed for ClassicTIFF"); return (0); } + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 8, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong8(value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_LONG8, count, @@ -2347,6 +2458,11 @@ static int TIFFWriteDirectoryTagCheckedSlong8Array(TIFF *tif, uint32_t *ndir, "SLONG8 not allowed for ClassicTIFF"); return (0); } + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 8, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong8((uint64_t *)value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_SLONG8, count, @@ -2370,16 +2486,17 @@ static int TIFFWriteDirectoryTagCheckedRational(TIFF *tif, uint32_t *ndir, TIFFErrorExtR(tif, module, "Not-a-number value is illegal"); return 0; } - /*--Rational2Double: New function also used for non-custom rational tags. - * However, could be omitted here, because - * TIFFWriteDirectoryTagCheckedRational() is not used by code for custom - * tags, only by code for named-tiff-tags like FIELD_RESOLUTION and - * FIELD_POSITION */ - else + + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ { - DoubleToRational(value, &m[0], &m[1]); + tif->tif_dir.td_dirdatasize_write += + (tif->tif_flags & TIFF_BIGTIFF) ? 0 : 0x8U; + (*ndir)++; + return 1; } + DoubleToRational(value, &m[0], &m[1]); + if (tif->tif_flags & TIFF_SWAB) { TIFFSwabLong(&m[0]); @@ -2402,6 +2519,11 @@ static int TIFFWriteDirectoryTagCheckedRationalArray(TIFF *tif, uint32_t *ndir, uint32_t nc; int o; assert(sizeof(uint32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir); + return 1; + } m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t)); if (m == NULL) { @@ -2433,6 +2555,11 @@ static int TIFFWriteDirectoryTagCheckedSrationalArray(TIFF *tif, uint32_t *ndir, uint32_t nc; int o; assert(sizeof(int32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir); + return 1; + } m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t)); if (m == NULL) { @@ -2465,6 +2592,11 @@ TIFFWriteDirectoryTagCheckedRationalDoubleArray(TIFF *tif, uint32_t *ndir, uint32_t nc; int o; assert(sizeof(uint32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(uint32_t), ndir); + return 1; + } m = _TIFFmallocExt(tif, count * 2 * sizeof(uint32_t)); if (m == NULL) { @@ -2495,6 +2627,11 @@ static int TIFFWriteDirectoryTagCheckedSrationalDoubleArray( uint32_t nc; int o; assert(sizeof(int32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count * 2, sizeof(int32_t), ndir); + return 1; + } m = _TIFFmallocExt(tif, count * 2 * sizeof(int32_t)); if (m == NULL) { @@ -2816,6 +2953,11 @@ static int TIFFWriteDirectoryTagCheckedFloatArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x40000000); assert(sizeof(float) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 4, ndir); + return 1; + } TIFFCvtNativeToIEEEFloat(tif, count, &value); if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfFloat(value, count); @@ -2830,6 +2972,11 @@ static int TIFFWriteDirectoryTagCheckedDoubleArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x20000000); assert(sizeof(double) == 8); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 8, ndir); + return 1; + } TIFFCvtNativeToIEEEDouble(tif, count, &value); if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfDouble(value, count); @@ -2843,6 +2990,11 @@ static int TIFFWriteDirectoryTagCheckedIfdArray(TIFF *tif, uint32_t *ndir, { assert(count < 0x40000000); assert(sizeof(uint32_t) == 4); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 4, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong(value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD, count, @@ -2857,6 +3009,11 @@ static int TIFFWriteDirectoryTagCheckedIfd8Array(TIFF *tif, uint32_t *ndir, assert(count < 0x20000000); assert(sizeof(uint64_t) == 8); assert(tif->tif_flags & TIFF_BIGTIFF); + if (dir == NULL) /* Just evaluate IFD data size and increment ndir. */ + { + EvaluateIFDdatasizeWrite(tif, count, 8, ndir); + return 1; + } if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong8(value, count); return (TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_IFD8, count, @@ -2973,15 +3130,15 @@ static int TIFFLinkDirectory(TIFF *tif) "Error writing SubIFD directory link"); return (0); } + /* * Advance to the next SubIFD or, if this is - * the last one configured, revert back to the - * normal directory linkage. + * the last one configured, reverting back to the + * normal directory linkage is done in TIFFWriteDirectorySec() + * by tif->tif_flags &= ~TIFF_INSUBIFD;. */ if (--tif->tif_nsubifd) tif->tif_subifdoff += 4; - else - tif->tif_flags &= ~TIFF_INSUBIFD; return (1); } else @@ -2997,19 +3154,23 @@ static int TIFFLinkDirectory(TIFF *tif) "Error writing SubIFD directory link"); return (0); } + /* * Advance to the next SubIFD or, if this is - * the last one configured, revert back to the - * normal directory linkage. + * the last one configured, reverting back to the + * normal directory linkage is done in TIFFWriteDirectorySec() + * by tif->tif_flags &= ~TIFF_INSUBIFD;. */ if (--tif->tif_nsubifd) tif->tif_subifdoff += 8; - else - tif->tif_flags &= ~TIFF_INSUBIFD; return (1); } } + /* + * Handle main-IFDs + */ + tdir_t ndir = 1; /* count current number of main-IFDs */ if (!(tif->tif_flags & TIFF_BIGTIFF)) { uint32_t m; @@ -3030,18 +3191,26 @@ static int TIFFLinkDirectory(TIFF *tif) TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header"); return (0); } + if (!tif->tif_dir.td_iswrittentofile) + tif->tif_curdircount = 0; return (1); } /* * Not the first directory, search to the last and append. */ - if (tif->tif_lastdiroff != 0) + tdir_t dirn = 0; + if (tif->tif_lastdiroff != 0 && + _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn)) { + /* Start searching from the lastely written IFD. Thus get its IFD + * number. */ nextdir = (uint32_t)tif->tif_lastdiroff; + ndir = dirn + 1; } else { nextdir = tif->tif_header.classic.tiff_diroff; + ndir = 1; /* start searching from the first IFD */ } while (1) @@ -3076,10 +3245,12 @@ static int TIFFLinkDirectory(TIFF *tif) break; } nextdir = nextnextdir; + ndir++; } } else { + /*- BigTIFF -*/ uint64_t m; uint64_t nextdir; m = tif->tif_diroff; @@ -3098,18 +3269,26 @@ static int TIFFLinkDirectory(TIFF *tif) TIFFErrorExtR(tif, tif->tif_name, "Error writing TIFF header"); return (0); } + if (!tif->tif_dir.td_iswrittentofile) + tif->tif_curdircount = 0; return (1); } /* * Not the first directory, search to the last and append. */ - if (tif->tif_lastdiroff != 0) + tdir_t dirn = 0; + if (tif->tif_lastdiroff != 0 && + _TIFFGetDirNumberFromOffset(tif, tif->tif_lastdiroff, &dirn)) { + /* Start searching from the lastely written IFD. Thus get its IFD + * number. */ nextdir = tif->tif_lastdiroff; + ndir = dirn + 1; } else { nextdir = tif->tif_header.big.tiff_diroff; + ndir = 1; /* start searching from the first IFD */ } while (1) { @@ -3126,9 +3305,9 @@ static int TIFFLinkDirectory(TIFF *tif) TIFFSwabLong8(&dircount64); if (dircount64 > 0xFFFF) { - TIFFErrorExtR( - tif, module, - "Sanity check on tag count failed, likely corrupt TIFF"); + TIFFErrorExtR(tif, module, + "Sanity check on tag count failed, " + "likely corrupt TIFF"); return (0); } dircount = (uint16_t)dircount64; @@ -3152,8 +3331,20 @@ static int TIFFLinkDirectory(TIFF *tif) break; } nextdir = nextnextdir; + ndir++; } } + /* Offset of next IFD is written to file. + * Update number of main-IFDs in file. + * However, tif_curdircount shall count only newly written main-IFDs with + * entries and not only number of linked offsets! Thus, tif_curdircount is + * incremented at the end of TIFFWriteDirectorySec(). + * TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs' + * 0 means 'empty file opened for writing, but no IFD written yet' */ + if (!tif->tif_dir.td_iswrittentofile && !(tif->tif_flags & TIFF_INSUBIFD)) + { + tif->tif_curdircount = ndir; + } return (1); } @@ -3197,9 +3388,9 @@ int _TIFFRewriteField(TIFF *tif, uint16_t tag, TIFFDataType in_datatype, /* -------------------------------------------------------------------- */ if (isMapped(tif)) { - TIFFErrorExtR( - tif, module, - "Memory mapped files not currently supported for this operation."); + TIFFErrorExtR(tif, module, + "Memory mapped files not currently supported for " + "this operation."); return 0; } diff --git a/3rdparty/libtiff/tif_fax3.c b/3rdparty/libtiff/tif_fax3.c index a3c645cb68..01a784730b 100644 --- a/3rdparty/libtiff/tif_fax3.c +++ b/3rdparty/libtiff/tif_fax3.c @@ -41,6 +41,14 @@ #include "t4.h" #include +#ifndef EOF_REACHED_COUNT_THRESHOLD +/* Arbitrary threshold to avoid corrupted single-strip files with extremely + * large imageheight to cause apparently endless looping, such as in + * https://gitlab.com/libtiff/libtiff/-/issues/583 + */ +#define EOF_REACHED_COUNT_THRESHOLD 8192 +#endif + /* * Compression+decompression state blocks are * derived from this ``base state'' block. @@ -77,6 +85,8 @@ typedef struct uint32_t data; /* current i/o byte/word */ int bit; /* current i/o bit in byte */ int EOLcnt; /* count of EOL codes recognized */ + int eofReachedCount; /* number of times decode has been called with + EOF already reached */ TIFFFaxFillFunc fill; /* fill routine */ uint32_t *runs; /* b&w runs for current/previous row */ uint32_t nruns; /* size of the refruns / curruns arrays */ @@ -120,6 +130,7 @@ typedef struct int EOLcnt; /* # EOL codes recognized */ \ const unsigned char *bitmap = sp->bitmap; /* input data bit reverser */ \ const TIFFFaxTabEnt *TabEnt + #define DECLARE_STATE_2D(tif, sp, mod) \ DECLARE_STATE(tif, sp, mod); \ int b1; /* next change on prev line */ \ @@ -162,6 +173,7 @@ static int Fax3PreDecode(TIFF *tif, uint16_t s) sp->bit = 0; /* force initial read */ sp->data = 0; sp->EOLcnt = 0; /* force initial scan for EOL */ + sp->eofReachedCount = 0; /* * Decoder assumes lsb-to-msb bit order. Note that we select * this here rather than in Fax3SetupState so that viewers can @@ -232,7 +244,12 @@ static void Fax3PrematureEOF(const char *module, TIFF *tif, uint32_t line, line, isTiled(tif) ? "tile" : "strip", (isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip), a0); } -#define prematureEOF(a0) Fax3PrematureEOF(module, tif, sp->line, a0) +#define prematureEOF(a0) \ + do \ + { \ + Fax3PrematureEOF(module, tif, sp->line, a0); \ + ++sp->eofReachedCount; \ + } while (0) #define Nop @@ -252,6 +269,14 @@ static int Fax3Decode1D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); return (-1); } + if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD) + { + TIFFErrorExtR( + tif, module, + "End of file has already been reached %d times within that strip", + sp->eofReachedCount); + return (-1); + } CACHE_STATE(tif, sp); thisrun = sp->curruns; while (occ > 0) @@ -302,6 +327,14 @@ static int Fax3Decode2D(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); return (-1); } + if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD) + { + TIFFErrorExtR( + tif, module, + "End of file has already been reached %d times within that strip", + sp->eofReachedCount); + return (-1); + } CACHE_STATE(tif, sp); while (occ > 0) { @@ -536,7 +569,11 @@ static int Fax3SetupState(TIFF *tif) TIFFroundup and TIFFSafeMultiply return zero on integer overflow */ - dsp->runs = (uint32_t *)NULL; + if (dsp->runs != NULL) + { + _TIFFfreeExt(tif, dsp->runs); + dsp->runs = (uint32_t *)NULL; + } dsp->nruns = TIFFroundup_32(rowpixels + 1, 32); if (needsRefLine) { @@ -578,6 +615,10 @@ static int Fax3SetupState(TIFF *tif) * is referenced. The reference line must * be initialized to be ``white'' (done elsewhere). */ + if (esp->refline != NULL) + { + _TIFFfreeExt(tif, esp->refline); + } esp->refline = (unsigned char *)_TIFFmallocExt(tif, rowbytes); if (esp->refline == NULL) { @@ -1514,7 +1555,16 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); return (-1); } + if (sp->eofReachedCount >= EOF_REACHED_COUNT_THRESHOLD) + { + TIFFErrorExtR( + tif, module, + "End of file has already been reached %d times within that strip", + sp->eofReachedCount); + return (-1); + } CACHE_STATE(tif, sp); + int start = sp->line; while (occ > 0) { a0 = 0; @@ -1563,7 +1613,9 @@ static int Fax4Decode(TIFF *tif, uint8_t *buf, tmsize_t occ, uint16_t s) } (*sp->fill)(buf, thisrun, pa, lastx); UNCACHE_STATE(tif, sp); - return (sp->line ? 1 : -1); /* don't error on badly-terminated strips */ + return (sp->line != start + ? 1 + : -1); /* don't error on badly-terminated strips */ } UNCACHE_STATE(tif, sp); return (1); diff --git a/3rdparty/libtiff/tif_getimage.c b/3rdparty/libtiff/tif_getimage.c index 41f7dfd77e..6c7b5031a1 100644 --- a/3rdparty/libtiff/tif_getimage.c +++ b/3rdparty/libtiff/tif_getimage.c @@ -760,6 +760,12 @@ static int gtTileContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, toskew = -(int32_t)(tw - w); } + if (tw == 0 || th == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero"); + return (0); + } + /* * Leftmost tile is clipped on left side if col_offset > 0. */ @@ -916,6 +922,12 @@ static int gtTileSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, break; } + if (tw == 0 || th == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "tile width or height is zero"); + return (0); + } + /* * Leftmost tile is clipped on left side if col_offset > 0. */ @@ -1092,6 +1104,11 @@ static int gtStripContig(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, } TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + if (rowsperstrip == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero"); + return (0); + } scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); @@ -1216,6 +1233,12 @@ static int gtStripSeparate(TIFFRGBAImage *img, uint32_t *raster, uint32_t w, } TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + if (rowsperstrip == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero"); + return (0); + } + scanline = TIFFScanlineSize(tif); fromskew = (w < imagewidth ? imagewidth - w : 0); for (row = 0; row < h; row += nrow) @@ -3213,6 +3236,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster, } TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + + if (rowsperstrip == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), "rowsperstrip is zero"); + return (0); + } + if ((row % rowsperstrip) != 0) { TIFFErrorExtR( @@ -3224,6 +3254,13 @@ int TIFFReadRGBAStripExt(TIFF *tif, uint32_t row, uint32_t *raster, if (TIFFRGBAImageOK(tif, emsg) && TIFFRGBAImageBegin(&img, tif, stop_on_error, emsg)) { + if (row >= img.height) + { + TIFFErrorExtR(tif, TIFFFileName(tif), + "Invalid row passed to TIFFReadRGBAStrip()."); + TIFFRGBAImageEnd(&img); + return (0); + } img.row_offset = row; img.col_offset = 0; @@ -3282,6 +3319,13 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster, TIFFGetFieldDefaulted(tif, TIFFTAG_TILEWIDTH, &tile_xsize); TIFFGetFieldDefaulted(tif, TIFFTAG_TILELENGTH, &tile_ysize); + if (tile_xsize == 0 || tile_ysize == 0) + { + TIFFErrorExtR(tif, TIFFFileName(tif), + "tile_xsize or tile_ysize is zero"); + return (0); + } + if ((col % tile_xsize) != 0 || (row % tile_ysize) != 0) { TIFFErrorExtR(tif, TIFFFileName(tif), @@ -3301,6 +3345,14 @@ int TIFFReadRGBATileExt(TIFF *tif, uint32_t col, uint32_t row, uint32_t *raster, return (0); } + if (col >= img.width || row >= img.height) + { + TIFFErrorExtR(tif, TIFFFileName(tif), + "Invalid row/col passed to TIFFReadRGBATile()."); + TIFFRGBAImageEnd(&img); + return (0); + } + /* * The TIFFRGBAImageGet() function doesn't allow us to get off the * edge of the image, even to fill an otherwise valid tile. So we diff --git a/3rdparty/libtiff/tif_jbig.c b/3rdparty/libtiff/tif_jbig.c index 7e455ad1ce..bb0de9e6e1 100644 --- a/3rdparty/libtiff/tif_jbig.c +++ b/3rdparty/libtiff/tif_jbig.c @@ -92,6 +92,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s) jbg_strerror(decodeStatus) #endif ); + memset(buffer, 0, (size_t)size); jbg_dec_free(&decoder); return 0; } @@ -99,6 +100,7 @@ static int JBIGDecode(TIFF *tif, uint8_t *buffer, tmsize_t size, uint16_t s) decodedSize = jbg_dec_getsize(&decoder); if ((tmsize_t)decodedSize < size) { + memset(buffer + decodedSize, 0, (size_t)(size - decodedSize)); TIFFWarningExtR(tif, "JBIG", "Only decoded %lu bytes, whereas %" TIFF_SSIZE_FORMAT " requested", diff --git a/3rdparty/libtiff/tif_jpeg.c b/3rdparty/libtiff/tif_jpeg.c index 250144f211..10aed54635 100644 --- a/3rdparty/libtiff/tif_jpeg.c +++ b/3rdparty/libtiff/tif_jpeg.c @@ -73,43 +73,6 @@ int TIFFReInitJPEG_12(TIFF *tif, const JPEGOtherSettings *otherSettings, int scheme, int is_encode); int TIFFJPEGIsFullStripRequired_12(TIFF *tif); -/* We undefine FAR to avoid conflict with JPEG definition */ - -#ifdef FAR -#undef FAR -#endif - -/* - Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is - not defined. Unfortunately, the MinGW and Borland compilers include - a typedef for INT32, which causes a conflict. MSVC does not include - a conflicting typedef given the headers which are included. -*/ -#if defined(__BORLANDC__) || defined(__MINGW32__) -#define XMD_H 1 -#endif - -/* - The windows RPCNDR.H file defines boolean, but defines it with the - unsigned char size. You should compile JPEG library using appropriate - definitions in jconfig.h header, but many users compile library in wrong - way. That causes errors of the following type: - - "JPEGLib: JPEG parameter struct mismatch: library thinks size is 432, - caller expects 464" - - For such users we will fix the problem here. See install.doc file from - the JPEG library distribution for details. -*/ - -/* Define "boolean" as unsigned char, not int, per Windows custom. */ -#if defined(__WIN32__) && !defined(__MINGW32__) -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ -#endif - #include "jerror.h" #include "jpeglib.h" @@ -125,18 +88,18 @@ typedef unsigned char boolean; * 16bit value? */ -/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 2.2 which +/* HAVE_JPEGTURBO_DUAL_MODE_8_12 is defined for libjpeg-turbo >= 3.0 which * adds a dual-mode 8/12 bit API in the same library. */ #if defined(HAVE_JPEGTURBO_DUAL_MODE_8_12) #define JPEG_DUAL_MODE_8_12 /* Start by undefining BITS_IN_JSAMPLE which is always set to 8 in libjpeg-turbo - * >= 2.2 Cf + * >= 3.0 Cf * https://github.com/libjpeg-turbo/libjpeg-turbo/commit/8b9bc4b9635a2a047fb23ebe70c9acd728d3f99b */ #undef BITS_IN_JSAMPLE -/* libjpeg-turbo >= 2.2 adds J12xxxx datatypes for the 12-bit mode. */ +/* libjpeg-turbo >= 3.0 adds J12xxxx datatypes for the 12-bit mode. */ #if defined(FROM_TIF_JPEG_12) #define BITS_IN_JSAMPLE 12 #define TIFF_JSAMPLE J12SAMPLE @@ -182,9 +145,20 @@ typedef unsigned char boolean; #define LONGJMP(jbuf, code) longjmp(jbuf, code) #define JMP_BUF jmp_buf +#ifndef TIFF_jpeg_destination_mgr_defined +#define TIFF_jpeg_destination_mgr_defined typedef struct jpeg_destination_mgr jpeg_destination_mgr; +#endif + +#ifndef TIFF_jpeg_source_mgr_defined +#define TIFF_jpeg_source_mgr_defined typedef struct jpeg_source_mgr jpeg_source_mgr; +#endif + +#ifndef TIFF_jpeg_error_mgr_defined +#define TIFF_jpeg_error_mgr_defined typedef struct jpeg_error_mgr jpeg_error_mgr; +#endif /* * State block for each open TIFF file using @@ -1241,6 +1215,12 @@ int TIFFJPEGIsFullStripRequired(TIFF *tif) * For PC 2, scale down the expected strip/tile size * to match a downsampled component */ + if (sp->h_sampling == 0 || sp->v_sampling == 0) + { + TIFFErrorExtR(tif, module, + "JPEG horizontal or vertical sampling is zero"); + return (0); + } segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); } @@ -1471,7 +1451,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; if (sp->bytesperline == 0) + { + memset(buf, 0, (size_t)cc); return 0; + } nrows = cc / sp->bytesperline; if (cc % sp->bytesperline) @@ -1492,7 +1475,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) JSAMPROW bufptr = (JSAMPROW)buf; if (TIFFjpeg_read_scanlines(sp, &bufptr, 1) != 1) + { + memset(buf, 0, (size_t)cc); return (0); + } ++tif->tif_row; buf += sp->bytesperline; @@ -1526,7 +1512,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) sp->src.bytes_in_buffer = (size_t)tif->tif_rawcc; if (sp->bytesperline == 0) + { + memset(buf, 0, (size_t)cc); return 0; + } nrows = cc / sp->bytesperline; if (cc % sp->bytesperline) @@ -1562,7 +1551,10 @@ static int JPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) * for 12bit data, which we need to repack. */ if (TIFFjpeg_read_scanlines(sp, &line_work_buf, 1) != 1) + { + memset(buf, 0, (size_t)cc); return (0); + } if (sp->cinfo.d.data_precision == 12) { @@ -2190,6 +2182,12 @@ static int JPEGPreEncode(TIFF *tif, uint16_t s) /* for PC 2, scale down the strip/tile size * to match a downsampled component */ + if (sp->h_sampling == 0 || sp->v_sampling == 0) + { + TIFFErrorExtR(tif, module, + "JPEG horizontal or vertical sampling is zero"); + return (0); + } segment_width = TIFFhowmany_32(segment_width, sp->h_sampling); segment_height = TIFFhowmany_32(segment_height, sp->v_sampling); } diff --git a/3rdparty/libtiff/tif_lerc.c b/3rdparty/libtiff/tif_lerc.c index 4f357a6011..d57b1d253d 100644 --- a/3rdparty/libtiff/tif_lerc.c +++ b/3rdparty/libtiff/tif_lerc.c @@ -71,6 +71,9 @@ typedef struct uint8_t *uncompressed_buffer; unsigned int uncompressed_offset; + uint8_t *uncompressed_buffer_multiband; + unsigned int uncompressed_buffer_multiband_alloc; + unsigned int mask_size; uint8_t *mask_buffer; @@ -86,9 +89,9 @@ typedef struct TIFFVSetMethod vsetparent; /* super-class method */ } LERCState; -#define LState(tif) ((LERCState *)(tif)->tif_data) -#define DecoderState(tif) LState(tif) -#define EncoderState(tif) LState(tif) +#define GetLERCState(tif) ((LERCState *)(tif)->tif_data) +#define LERCDecoderState(tif) GetLERCState(tif) +#define LERCEncoderState(tif) GetLERCState(tif) static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); @@ -101,7 +104,7 @@ static int LERCFixupTags(TIFF *tif) static int LERCSetupDecode(TIFF *tif) { - LERCState *sp = DecoderState(tif); + LERCState *sp = LERCDecoderState(tif); assert(sp != NULL); @@ -168,7 +171,7 @@ static int GetLercDataType(TIFF *tif) return -1; } -static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module) +static int SetupBuffers(TIFF *tif, LERCState *sp, const char *module) { TIFFDirectory *td = &tif->tif_dir; uint64_t new_size_64; @@ -202,8 +205,9 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module) sp->uncompressed_size = new_size; /* add some margin as we are going to use it also to store deflate/zstd - * compressed data */ - new_alloc_64 = 100 + new_size_64 + new_size_64 / 3; + * compressed data. We also need extra margin when writing very small + * rasters with one mask per band. */ + new_alloc_64 = 256 + new_size_64 + new_size_64 / 3; #ifdef ZSTD_SUPPORT { size_t zstd_max = ZSTD_compressBound((size_t)new_size_64); @@ -243,11 +247,17 @@ static int SetupUncompressedBuffer(TIFF *tif, LERCState *sp, const char *module) td->td_sampleinfo[td->td_extrasamples - 1] == EXTRASAMPLE_UNASSALPHA && GetLercDataType(tif) == 1) || (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && - (td->td_planarconfig == PLANARCONFIG_SEPARATE || - td->td_samplesperpixel == 1) && (td->td_bitspersample == 32 || td->td_bitspersample == 64))) { unsigned int mask_size = sp->segment_width * sp->segment_height; +#if LERC_AT_LEAST_VERSION(3, 0, 0) + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && + td->td_planarconfig == PLANARCONFIG_CONTIG) + { + /* We may need one mask per band */ + mask_size *= td->td_samplesperpixel; + } +#endif if (sp->mask_size < mask_size) { void *mask_buffer = @@ -277,9 +287,9 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) static const char module[] = "LERCPreDecode"; lerc_status lerc_ret; TIFFDirectory *td = &tif->tif_dir; - LERCState *sp = DecoderState(tif); + LERCState *sp = LERCDecoderState(tif); int lerc_data_type; - unsigned int infoArray[8]; + unsigned int infoArray[9]; unsigned nomask_bands = td->td_samplesperpixel; int ndims; int use_mask = 0; @@ -295,7 +305,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) if (lerc_data_type < 0) return 0; - if (!SetupUncompressedBuffer(tif, sp, module)) + if (!SetupBuffers(tif, sp, module)) return 0; if (sp->additional_compression != LERC_ADD_COMPRESSION_NONE) @@ -400,7 +410,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) } lerc_ret = - lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 8, 0); + lerc_getBlobInfo(lerc_data, lerc_data_size, infoArray, NULL, 9, 0); if (lerc_ret != 0) { TIFFErrorExtR(tif, module, "lerc_getBlobInfo() failed"); @@ -418,18 +428,16 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) use_mask = 1; nomask_bands--; } - else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && - (td->td_planarconfig == PLANARCONFIG_SEPARATE || - td->td_samplesperpixel == 1) && - (td->td_bitspersample == 32 || td->td_bitspersample == 64)) + else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP) { use_mask = 1; } ndims = td->td_planarconfig == PLANARCONFIG_CONTIG ? nomask_bands : 1; - /* Info returned in infoArray is { version, dataType, nDim, nCols, - nRows, nBands, nValidPixels, blobSize } */ + /* Info returned in infoArray is { version, dataType, nDim/nDepth, nCols, + nRows, nBands, nValidPixels, blobSize, + and starting with liblerc 3.0 nRequestedMasks } */ if (infoArray[0] != (unsigned)sp->lerc_version) { TIFFWarningExtR(tif, module, @@ -442,12 +450,29 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) infoArray[1], lerc_data_type); return 0; } - if (infoArray[2] != (unsigned)ndims) + + const unsigned nFoundDims = infoArray[2]; +#if LERC_AT_LEAST_VERSION(3, 0, 0) + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && + td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_samplesperpixel > 1) + { + if (nFoundDims != 1 && nFoundDims != (unsigned)ndims) + { + TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: 1 or %d", + nFoundDims, ndims); + return 0; + } + } + else +#endif + if (nFoundDims != (unsigned)ndims) { TIFFErrorExtR(tif, module, "Unexpected nDim: %d. Expected: %d", - infoArray[2], ndims); + nFoundDims, ndims); return 0; } + if (infoArray[3] != sp->segment_width) { TIFFErrorExtR(tif, module, "Unexpected nCols: %d. Expected: %du", @@ -460,12 +485,38 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) infoArray[4], sp->segment_height); return 0; } - if (infoArray[5] != 1) + + const unsigned nFoundBands = infoArray[5]; + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && + td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_samplesperpixel > 1 && nFoundDims == 1) + { +#if !LERC_AT_LEAST_VERSION(3, 0, 0) + if (nFoundBands == td->td_samplesperpixel) + { + TIFFErrorExtR( + tif, module, + "Unexpected nBands: %d. This file may have been generated with " + "a liblerc version >= 3.0, with one mask per band, and is not " + "supported by this older version of liblerc", + nFoundBands); + return 0; + } +#endif + if (nFoundBands != td->td_samplesperpixel) + { + TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d", + nFoundBands, td->td_samplesperpixel); + return 0; + } + } + else if (nFoundBands != 1) { TIFFErrorExtR(tif, module, "Unexpected nBands: %d. Expected: %d", - infoArray[5], 1); + nFoundBands, 1); return 0; } + if (infoArray[7] != lerc_data_size) { TIFFErrorExtR(tif, module, "Unexpected blobSize: %d. Expected: %u", @@ -473,13 +524,75 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) return 0; } - lerc_ret = lerc_decode(lerc_data, lerc_data_size, + int nRequestedMasks = use_mask ? 1 : 0; #if LERC_AT_LEAST_VERSION(3, 0, 0) - use_mask ? 1 : 0, + const int nFoundMasks = infoArray[8]; + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && + td->td_planarconfig == PLANARCONFIG_CONTIG && + td->td_samplesperpixel > 1 && nFoundDims == 1) + { + if (nFoundMasks != 0 && nFoundMasks != td->td_samplesperpixel) + { + TIFFErrorExtR(tif, module, + "Unexpected nFoundMasks: %d. Expected: 0 or %d", + nFoundMasks, td->td_samplesperpixel); + return 0; + } + nRequestedMasks = nFoundMasks; + } + else + { + if (nFoundMasks != 0 && nFoundMasks != 1) + { + TIFFErrorExtR(tif, module, + "Unexpected nFoundMasks: %d. Expected: 0 or 1", + nFoundMasks); + return 0; + } + } + if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && nFoundMasks == 0) + { + nRequestedMasks = 0; + use_mask = 0; + } #endif - use_mask ? sp->mask_buffer : NULL, ndims, - sp->segment_width, sp->segment_height, 1, - lerc_data_type, sp->uncompressed_buffer); + + const unsigned nb_pixels = sp->segment_width * sp->segment_height; + +#if LERC_AT_LEAST_VERSION(3, 0, 0) + if (nRequestedMasks > 1) + { + unsigned int num_bytes_needed = + nb_pixels * td->td_samplesperpixel * (td->td_bitspersample / 8); + if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed) + { + _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband); + sp->uncompressed_buffer_multiband = + _TIFFmallocExt(tif, num_bytes_needed); + if (!sp->uncompressed_buffer_multiband) + { + sp->uncompressed_buffer_multiband_alloc = 0; + return 0; + } + sp->uncompressed_buffer_multiband_alloc = num_bytes_needed; + } + lerc_ret = lerc_decode(lerc_data, lerc_data_size, nRequestedMasks, + sp->mask_buffer, nFoundDims, sp->segment_width, + sp->segment_height, nFoundBands, lerc_data_type, + sp->uncompressed_buffer_multiband); + } + else +#endif + { + lerc_ret = + lerc_decode(lerc_data, lerc_data_size, +#if LERC_AT_LEAST_VERSION(3, 0, 0) + nRequestedMasks, +#endif + use_mask ? sp->mask_buffer : NULL, nFoundDims, + sp->segment_width, sp->segment_height, nFoundBands, + lerc_data_type, sp->uncompressed_buffer); + } if (lerc_ret != 0) { TIFFErrorExtR(tif, module, "lerc_decode() failed"); @@ -515,7 +628,6 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) } else if (use_mask && td->td_sampleformat == SAMPLEFORMAT_IEEEFP) { - const unsigned nb_pixels = sp->segment_width * sp->segment_height; unsigned i; #if WORDS_BIGENDIAN const unsigned char nan_bytes[] = {0x7f, 0xc0, 0, 0}; @@ -525,23 +637,104 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) float nan_float32; memcpy(&nan_float32, nan_bytes, 4); - if (td->td_bitspersample == 32) + if (td->td_planarconfig == PLANARCONFIG_SEPARATE || + td->td_samplesperpixel == 1) { - for (i = 0; i < nb_pixels; i++) + if (td->td_bitspersample == 32) { - if (sp->mask_buffer[i] == 0) - ((float *)sp->uncompressed_buffer)[i] = nan_float32; + for (i = 0; i < nb_pixels; i++) + { + if (sp->mask_buffer[i] == 0) + ((float *)sp->uncompressed_buffer)[i] = nan_float32; + } + } + else + { + const double nan_float64 = nan_float32; + for (i = 0; i < nb_pixels; i++) + { + if (sp->mask_buffer[i] == 0) + ((double *)sp->uncompressed_buffer)[i] = nan_float64; + } } } + else if (nRequestedMasks == 1) + { + assert(nFoundDims == td->td_samplesperpixel); + assert(nFoundBands == 1); + + unsigned k = 0; + if (td->td_bitspersample == 32) + { + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; j++) + { + if (sp->mask_buffer[i] == 0) + ((float *)sp->uncompressed_buffer)[k] = nan_float32; + ++k; + } + } + } + else + { + const double nan_float64 = nan_float32; + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; j++) + { + if (sp->mask_buffer[i] == 0) + ((double *)sp->uncompressed_buffer)[k] = + nan_float64; + ++k; + } + } + } + } +#if LERC_AT_LEAST_VERSION(3, 0, 0) else { - const double nan_float64 = nan_float32; - for (i = 0; i < nb_pixels; i++) + assert(nRequestedMasks == td->td_samplesperpixel); + assert(nFoundDims == 1); + assert(nFoundBands == td->td_samplesperpixel); + + unsigned k = 0; + if (td->td_bitspersample == 32) { - if (sp->mask_buffer[i] == 0) - ((double *)sp->uncompressed_buffer)[i] = nan_float64; + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; j++) + { + if (sp->mask_buffer[i + j * nb_pixels] == 0) + ((float *)sp->uncompressed_buffer)[k] = nan_float32; + else + ((float *)sp->uncompressed_buffer)[k] = + ((float *)sp->uncompressed_buffer_multiband) + [i + j * nb_pixels]; + ++k; + } + } + } + else + { + const double nan_float64 = nan_float32; + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; j++) + { + if (sp->mask_buffer[i + j * nb_pixels] == 0) + ((double *)sp->uncompressed_buffer)[k] = + nan_float64; + else + ((double *)sp->uncompressed_buffer)[k] = + ((double *)sp->uncompressed_buffer_multiband) + [i + j * nb_pixels]; + ++k; + } + } } } +#endif } return 1; @@ -553,7 +746,7 @@ static int LERCPreDecode(TIFF *tif, uint16_t s) static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { static const char module[] = "LERCDecode"; - LERCState *sp = DecoderState(tif); + LERCState *sp = LERCDecoderState(tif); (void)s; assert(sp != NULL); @@ -561,6 +754,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->uncompressed_buffer == 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Uncompressed buffer not allocated"); return 0; } @@ -568,6 +762,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if ((uint64_t)sp->uncompressed_offset + (uint64_t)occ > sp->uncompressed_size) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Too many bytes read"); return 0; } @@ -580,7 +775,7 @@ static int LERCDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) static int LERCSetupEncode(TIFF *tif) { - LERCState *sp = EncoderState(tif); + LERCState *sp = LERCEncoderState(tif); assert(sp != NULL); if (sp->state & LSTATE_INIT_DECODE) @@ -599,7 +794,7 @@ static int LERCSetupEncode(TIFF *tif) static int LERCPreEncode(TIFF *tif, uint16_t s) { static const char module[] = "LERCPreEncode"; - LERCState *sp = EncoderState(tif); + LERCState *sp = LERCEncoderState(tif); int lerc_data_type; (void)s; @@ -611,7 +806,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s) if (lerc_data_type < 0) return 0; - if (!SetupUncompressedBuffer(tif, sp, module)) + if (!SetupBuffers(tif, sp, module)) return 0; return 1; @@ -623,7 +818,7 @@ static int LERCPreEncode(TIFF *tif, uint16_t s) static int LERCEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { static const char module[] = "LERCEncode"; - LERCState *sp = EncoderState(tif); + LERCState *sp = LERCEncoderState(tif); (void)s; assert(sp != NULL); @@ -649,8 +844,7 @@ static int LERCPostEncode(TIFF *tif) { lerc_status lerc_ret; static const char module[] = "LERCPostEncode"; - LERCState *sp = EncoderState(tif); - unsigned int numBytes = 0; + LERCState *sp = LERCEncoderState(tif); unsigned int numBytesWritten = 0; TIFFDirectory *td = &tif->tif_dir; int use_mask = 0; @@ -662,6 +856,9 @@ static int LERCPostEncode(TIFF *tif) return 0; } + int mask_count = 1; + const unsigned nb_pixels = sp->segment_width * sp->segment_height; + /* Extract alpha mask (if containing only 0 and 255 values, */ /* and compact array of regular bands */ if (td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_extrasamples > 0 && @@ -673,7 +870,6 @@ static int LERCPostEncode(TIFF *tif) const unsigned src_stride = td->td_samplesperpixel * (td->td_bitspersample / 8); unsigned i = 0; - const unsigned nb_pixels = sp->segment_width * sp->segment_height; use_mask = 1; for (i = 0; i < nb_pixels; i++) @@ -710,46 +906,78 @@ static int LERCPostEncode(TIFF *tif) } } else if (td->td_sampleformat == SAMPLEFORMAT_IEEEFP && - (td->td_planarconfig == PLANARCONFIG_SEPARATE || - dst_nbands == 1) && (td->td_bitspersample == 32 || td->td_bitspersample == 64)) { /* Check for NaN values */ unsigned i; - const unsigned nb_pixels = sp->segment_width * sp->segment_height; if (td->td_bitspersample == 32) { - for (i = 0; i < nb_pixels; i++) + if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1) { - const float val = ((float *)sp->uncompressed_buffer)[i]; - if (val != val) + unsigned k = 0; + for (i = 0; i < nb_pixels; i++) { - use_mask = 1; - break; + int count_nan = 0; + for (int j = 0; j < td->td_samplesperpixel; ++j) + { + const float val = ((float *)sp->uncompressed_buffer)[k]; + ++k; + if (val != val) + { + ++count_nan; + } + } + if (count_nan > 0) + { + use_mask = 1; + if (count_nan < td->td_samplesperpixel) + { + mask_count = td->td_samplesperpixel; + break; + } + } + } + } + else + { + for (i = 0; i < nb_pixels; i++) + { + const float val = ((float *)sp->uncompressed_buffer)[i]; + if (val != val) + { + use_mask = 1; + break; + } } } } else { - for (i = 0; i < nb_pixels; i++) - { - const double val = ((double *)sp->uncompressed_buffer)[i]; - if (val != val) - { - use_mask = 1; - break; - } - } - } - - if (use_mask) - { - if (td->td_bitspersample == 32) + if (td->td_planarconfig == PLANARCONFIG_CONTIG && dst_nbands > 1) { + unsigned k = 0; for (i = 0; i < nb_pixels; i++) { - const float val = ((float *)sp->uncompressed_buffer)[i]; - sp->mask_buffer[i] = (val == val) ? 255 : 0; + int count_nan = 0; + for (int j = 0; j < td->td_samplesperpixel; ++j) + { + const double val = + ((double *)sp->uncompressed_buffer)[k]; + ++k; + if (val != val) + { + ++count_nan; + } + } + if (count_nan > 0) + { + use_mask = 1; + if (count_nan < td->td_samplesperpixel) + { + mask_count = td->td_samplesperpixel; + break; + } + } } } else @@ -757,62 +985,168 @@ static int LERCPostEncode(TIFF *tif) for (i = 0; i < nb_pixels; i++) { const double val = ((double *)sp->uncompressed_buffer)[i]; - sp->mask_buffer[i] = (val == val) ? 255 : 0; + if (val != val) + { + use_mask = 1; + break; + } + } + } + } + + if (use_mask) + { + if (mask_count > 1) + { +#if LERC_AT_LEAST_VERSION(3, 0, 0) + unsigned int num_bytes_needed = + nb_pixels * dst_nbands * (td->td_bitspersample / 8); + if (sp->uncompressed_buffer_multiband_alloc < num_bytes_needed) + { + _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband); + sp->uncompressed_buffer_multiband = + _TIFFmallocExt(tif, num_bytes_needed); + if (!sp->uncompressed_buffer_multiband) + { + sp->uncompressed_buffer_multiband_alloc = 0; + return 0; + } + sp->uncompressed_buffer_multiband_alloc = num_bytes_needed; + } + + unsigned k = 0; + if (td->td_bitspersample == 32) + { + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; ++j) + { + const float val = + ((float *)sp->uncompressed_buffer)[k]; + ((float *)sp->uncompressed_buffer_multiband) + [i + j * nb_pixels] = val; + ++k; + sp->mask_buffer[i + j * nb_pixels] = + (val == val) ? 255 : 0; + } + } + } + else + { + for (i = 0; i < nb_pixels; i++) + { + for (int j = 0; j < td->td_samplesperpixel; ++j) + { + const double val = + ((double *)sp->uncompressed_buffer)[k]; + ((double *)sp->uncompressed_buffer_multiband) + [i + j * nb_pixels] = val; + ++k; + sp->mask_buffer[i + j * nb_pixels] = + (val == val) ? 255 : 0; + } + } + } +#else + TIFFErrorExtR(tif, module, + "lerc_encode() would need to create one mask per " + "sample, but this requires liblerc >= 3.0"); + return 0; +#endif + } + else if (td->td_planarconfig == PLANARCONFIG_CONTIG && + dst_nbands > 1) + { + if (td->td_bitspersample == 32) + { + for (i = 0; i < nb_pixels; i++) + { + const float val = + ((float *)sp->uncompressed_buffer)[i * dst_nbands]; + sp->mask_buffer[i] = (val == val) ? 255 : 0; + } + } + else + { + for (i = 0; i < nb_pixels; i++) + { + const double val = + ((double *)sp->uncompressed_buffer)[i * dst_nbands]; + sp->mask_buffer[i] = (val == val) ? 255 : 0; + } + } + } + else + { + if (td->td_bitspersample == 32) + { + for (i = 0; i < nb_pixels; i++) + { + const float val = ((float *)sp->uncompressed_buffer)[i]; + sp->mask_buffer[i] = (val == val) ? 255 : 0; + } + } + else + { + for (i = 0; i < nb_pixels; i++) + { + const double val = + ((double *)sp->uncompressed_buffer)[i]; + sp->mask_buffer[i] = (val == val) ? 255 : 0; + } } } } } -#if 0 - lerc_ret = lerc_computeCompressedSize( - sp->uncompressed_buffer, - sp->lerc_version, - GetLercDataType(tif), - td->td_planarconfig == PLANARCONFIG_CONTIG ? - dst_nbands : 1, - sp->segment_width, - sp->segment_height, - 1, - use_mask ? sp->mask_buffer : NULL, - sp->maxzerror, - &numBytes); - if( lerc_ret != 0 ) - { - TIFFErrorExtR(tif, module, - "lerc_computeCompressedSize() failed"); - return 0; - } -#else - numBytes = sp->uncompressed_alloc; + unsigned int estimated_compressed_size = sp->uncompressed_alloc; +#if LERC_AT_LEAST_VERSION(3, 0, 0) + if (mask_count > 1) + { + estimated_compressed_size += nb_pixels * mask_count / 8; + } #endif - if (sp->compressed_size < numBytes) + if (sp->compressed_size < estimated_compressed_size) { _TIFFfreeExt(tif, sp->compressed_buffer); - sp->compressed_buffer = _TIFFmallocExt(tif, numBytes); + sp->compressed_buffer = _TIFFmallocExt(tif, estimated_compressed_size); if (!sp->compressed_buffer) { sp->compressed_size = 0; return 0; } - sp->compressed_size = numBytes; + sp->compressed_size = estimated_compressed_size; } - lerc_ret = lerc_encodeForVersion( - sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif), - td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1, - sp->segment_width, sp->segment_height, 1, #if LERC_AT_LEAST_VERSION(3, 0, 0) - use_mask ? 1 : 0, + if (mask_count > 1) + { + lerc_ret = lerc_encodeForVersion( + sp->uncompressed_buffer_multiband, sp->lerc_version, + GetLercDataType(tif), 1, sp->segment_width, sp->segment_height, + dst_nbands, dst_nbands, sp->mask_buffer, sp->maxzerror, + sp->compressed_buffer, sp->compressed_size, &numBytesWritten); + } + else #endif - use_mask ? sp->mask_buffer : NULL, sp->maxzerror, sp->compressed_buffer, - sp->compressed_size, &numBytesWritten); + { + lerc_ret = lerc_encodeForVersion( + sp->uncompressed_buffer, sp->lerc_version, GetLercDataType(tif), + td->td_planarconfig == PLANARCONFIG_CONTIG ? dst_nbands : 1, + sp->segment_width, sp->segment_height, 1, +#if LERC_AT_LEAST_VERSION(3, 0, 0) + use_mask ? 1 : 0, +#endif + use_mask ? sp->mask_buffer : NULL, sp->maxzerror, + sp->compressed_buffer, sp->compressed_size, &numBytesWritten); + } if (lerc_ret != 0) { TIFFErrorExtR(tif, module, "lerc_encode() failed"); return 0; } - assert(numBytesWritten < numBytes); + assert(numBytesWritten < estimated_compressed_size); if (sp->additional_compression == LERC_ADD_COMPRESSION_DEFLATE) { @@ -950,7 +1284,7 @@ static int LERCPostEncode(TIFF *tif) static void LERCCleanup(TIFF *tif) { - LERCState *sp = LState(tif); + LERCState *sp = GetLERCState(tif); assert(sp != 0); @@ -958,6 +1292,7 @@ static void LERCCleanup(TIFF *tif) tif->tif_tagmethods.vsetfield = sp->vsetparent; _TIFFfreeExt(tif, sp->uncompressed_buffer); + _TIFFfreeExt(tif, sp->uncompressed_buffer_multiband); _TIFFfreeExt(tif, sp->compressed_buffer); _TIFFfreeExt(tif, sp->mask_buffer); @@ -995,7 +1330,7 @@ static const TIFFField LERCFields[] = { static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...) { - LERCState *sp = LState(tif); + LERCState *sp = GetLERCState(tif); int ret; va_list ap; va_start(ap, tag); @@ -1007,7 +1342,7 @@ static int LERCVSetFieldBase(TIFF *tif, uint32_t tag, ...) static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap) { static const char module[] = "LERCVSetField"; - LERCState *sp = LState(tif); + LERCState *sp = GetLERCState(tif); switch (tag) { @@ -1115,7 +1450,7 @@ static int LERCVSetField(TIFF *tif, uint32_t tag, va_list ap) static int LERCVGetField(TIFF *tif, uint32_t tag, va_list ap) { - LERCState *sp = LState(tif); + LERCState *sp = GetLERCState(tif); switch (tag) { @@ -1163,7 +1498,7 @@ int TIFFInitLERC(TIFF *tif, int scheme) tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, 1, sizeof(LERCState)); if (tif->tif_data == NULL) goto bad; - sp = LState(tif); + sp = GetLERCState(tif); /* * Override parent get/set field methods. diff --git a/3rdparty/libtiff/tif_luv.c b/3rdparty/libtiff/tif_luv.c index 021756d5d6..d19653550c 100644 --- a/3rdparty/libtiff/tif_luv.c +++ b/3rdparty/libtiff/tif_luv.c @@ -951,7 +951,8 @@ static int uv_encode(double u, double v, int em) /* encode (u',v') coordinates */ { - register int vi, ui; + unsigned int vi; + int ui; /* check for NaN */ if (u != u || v != v) @@ -980,8 +981,9 @@ static int uv_decode(double *up, double *vp, int c) /* decode (u',v') index */ { - int upper, lower; - register int ui, vi; + unsigned int upper, lower; + int ui; + unsigned int vi; if (c < 0 || c >= UV_NDIVS) return (-1); diff --git a/3rdparty/libtiff/tif_lzma.c b/3rdparty/libtiff/tif_lzma.c index 4cfd5e8821..db1c8b6829 100644 --- a/3rdparty/libtiff/tif_lzma.c +++ b/3rdparty/libtiff/tif_lzma.c @@ -44,6 +44,8 @@ typedef struct { TIFFPredictorState predict; + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ lzma_stream stream; lzma_filter filters[LZMA_FILTERS_MAX + 1]; lzma_options_delta opt_delta; /* delta filter options */ @@ -58,9 +60,9 @@ typedef struct TIFFVSetMethod vsetparent; /* super-class method */ } LZMAState; -#define LState(tif) ((LZMAState *)(tif)->tif_data) -#define DecoderState(tif) LState(tif) -#define EncoderState(tif) LState(tif) +#define GetLZMAState(tif) ((LZMAState *)(tif)->tif_data) +#define LZMADecoderState(tif) GetLZMAState(tif) +#define LZMAEncoderState(tif) GetLZMAState(tif) static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); @@ -106,7 +108,7 @@ static int LZMAFixupTags(TIFF *tif) static int LZMASetupDecode(TIFF *tif) { - LZMAState *sp = DecoderState(tif); + LZMAState *sp = LZMADecoderState(tif); assert(sp != NULL); @@ -127,7 +129,7 @@ static int LZMASetupDecode(TIFF *tif) static int LZMAPreDecode(TIFF *tif, uint16_t s) { static const char module[] = "LZMAPreDecode"; - LZMAState *sp = DecoderState(tif); + LZMAState *sp = LZMADecoderState(tif); lzma_ret ret; (void)s; @@ -156,18 +158,31 @@ static int LZMAPreDecode(TIFF *tif, uint16_t s) LZMAStrerror(ret)); return 0; } + + sp->read_error = 0; + return 1; } static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { static const char module[] = "LZMADecode"; - LZMAState *sp = DecoderState(tif); + LZMAState *sp = LZMADecoderState(tif); (void)s; assert(sp != NULL); assert(sp->state == LSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "LZMADecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + sp->stream.next_in = tif->tif_rawcp; sp->stream.avail_in = (size_t)tif->tif_rawcc; @@ -175,6 +190,9 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) sp->stream.avail_out = (size_t)occ; if ((tmsize_t)sp->stream.avail_out != occ) { + // read_error not set here as this is a usage issue that can be + // recovered in a following call. + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Liblzma cannot deal with buffers this size"); return 0; @@ -198,6 +216,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) lzma_stream_decoder(&sp->stream, lzma_memusage(&sp->stream), 0); if (r != LZMA_OK) { + sp->read_error = 1; + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Error initializing the stream decoder, %s", LZMAStrerror(r)); @@ -217,6 +237,8 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) } while (sp->stream.avail_out > 0); if (sp->stream.avail_out != 0) { + sp->read_error = 1; + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "Not enough data at scanline %" PRIu32 " (short %" TIFF_SIZE_FORMAT " bytes)", @@ -232,7 +254,7 @@ static int LZMADecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) static int LZMASetupEncode(TIFF *tif) { - LZMAState *sp = EncoderState(tif); + LZMAState *sp = LZMAEncoderState(tif); assert(sp != NULL); if (sp->state & LSTATE_INIT_DECODE) @@ -251,7 +273,7 @@ static int LZMASetupEncode(TIFF *tif) static int LZMAPreEncode(TIFF *tif, uint16_t s) { static const char module[] = "LZMAPreEncode"; - LZMAState *sp = EncoderState(tif); + LZMAState *sp = LZMAEncoderState(tif); lzma_ret ret; (void)s; @@ -283,7 +305,7 @@ static int LZMAPreEncode(TIFF *tif, uint16_t s) static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { static const char module[] = "LZMAEncode"; - LZMAState *sp = EncoderState(tif); + LZMAState *sp = LZMAEncoderState(tif); assert(sp != NULL); assert(sp->state == LSTATE_INIT_ENCODE); @@ -329,7 +351,7 @@ static int LZMAEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) static int LZMAPostEncode(TIFF *tif) { static const char module[] = "LZMAPostEncode"; - LZMAState *sp = EncoderState(tif); + LZMAState *sp = LZMAEncoderState(tif); lzma_ret ret; sp->stream.avail_in = 0; @@ -365,7 +387,7 @@ static int LZMAPostEncode(TIFF *tif) static void LZMACleanup(TIFF *tif) { - LZMAState *sp = LState(tif); + LZMAState *sp = GetLZMAState(tif); assert(sp != 0); @@ -388,7 +410,7 @@ static void LZMACleanup(TIFF *tif) static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap) { static const char module[] = "LZMAVSetField"; - LZMAState *sp = LState(tif); + LZMAState *sp = GetLZMAState(tif); switch (tag) { @@ -414,7 +436,7 @@ static int LZMAVSetField(TIFF *tif, uint32_t tag, va_list ap) static int LZMAVGetField(TIFF *tif, uint32_t tag, va_list ap) { - LZMAState *sp = LState(tif); + LZMAState *sp = GetLZMAState(tif); switch (tag) { @@ -457,7 +479,7 @@ int TIFFInitLZMA(TIFF *tif, int scheme) tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZMAState)); if (tif->tif_data == NULL) goto bad; - sp = LState(tif); + sp = GetLZMAState(tif); memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream)); /* diff --git a/3rdparty/libtiff/tif_lzw.c b/3rdparty/libtiff/tif_lzw.c index d631fa1049..4baf78e50b 100644 --- a/3rdparty/libtiff/tif_lzw.c +++ b/3rdparty/libtiff/tif_lzw.c @@ -161,8 +161,8 @@ typedef struct } LZWCodecState; #define LZWState(tif) ((LZWBaseState *)(tif)->tif_data) -#define DecoderState(tif) ((LZWCodecState *)LZWState(tif)) -#define EncoderState(tif) ((LZWCodecState *)LZWState(tif)) +#define LZWDecoderState(tif) ((LZWCodecState *)LZWState(tif)) +#define LZWEncoderState(tif) ((LZWCodecState *)LZWState(tif)) static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s); #ifdef LZW_COMPAT @@ -183,7 +183,7 @@ static int LZWFixupTags(TIFF *tif) static int LZWSetupDecode(TIFF *tif) { static const char module[] = "LZWSetupDecode"; - LZWCodecState *sp = DecoderState(tif); + LZWCodecState *sp = LZWDecoderState(tif); int code; if (sp == NULL) @@ -199,7 +199,7 @@ static int LZWSetupDecode(TIFF *tif) return (0); } - sp = DecoderState(tif); + sp = LZWDecoderState(tif); sp->dec_codetab = NULL; sp->dec_decode = NULL; @@ -245,7 +245,7 @@ static int LZWSetupDecode(TIFF *tif) static int LZWPreDecode(TIFF *tif, uint16_t s) { static const char module[] = "LZWPreDecode"; - LZWCodecState *sp = DecoderState(tif); + LZWCodecState *sp = LZWDecoderState(tif); (void)s; assert(sp != NULL); @@ -329,10 +329,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s) #ifdef WORDS_BIGENDIAN #define GetNextData(nextdata, bp) memcpy(&nextdata, bp, sizeof(nextdata)) #elif SIZEOF_WORDTYPE == 8 -#if defined(__GNUC__) && defined(__x86_64__) -#define GetNextData(nextdata, bp) \ - nextdata = __builtin_bswap64(*(uint64_t *)(bp)) -#elif defined(_M_X64) +#if defined(_M_X64) #define GetNextData(nextdata, bp) nextdata = _byteswap_uint64(*(uint64_t *)(bp)) #elif defined(__GNUC__) #define GetNextData(nextdata, bp) \ @@ -346,10 +343,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s) (((uint64_t)bp[6]) << 8) | (((uint64_t)bp[7])) #endif #elif SIZEOF_WORDTYPE == 4 -#if defined(__GNUC__) && defined(__i386__) -#define GetNextData(nextdata, bp) \ - nextdata = __builtin_bswap32(*(uint32_t *)(bp)) -#elif defined(_M_X86) +#if defined(_M_X86) #define GetNextData(nextdata, bp) \ nextdata = _byteswap_ulong(*(unsigned long *)(bp)) #elif defined(__GNUC__) @@ -409,7 +403,7 @@ static int LZWPreDecode(TIFF *tif, uint16_t s) static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) { static const char module[] = "LZWDecode"; - LZWCodecState *sp = DecoderState(tif); + LZWCodecState *sp = LZWDecoderState(tif); uint8_t *op = (uint8_t *)op0; tmsize_t occ = occ0; uint8_t *bp; @@ -423,6 +417,7 @@ static int LZWDecode(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) if (sp->read_error) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "LZWDecode: Scanline %" PRIu32 " cannot be read due to " "previous error", @@ -737,6 +732,7 @@ after_loop: if (occ > 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Not enough data at scanline %" PRIu32 " (short %" PRIu64 " bytes)", @@ -746,12 +742,14 @@ after_loop: return (1); no_eoi: + memset(op, 0, (size_t)occ); sp->read_error = 1; TIFFErrorExtR(tif, module, "LZWDecode: Strip %" PRIu32 " not terminated with EOI code", tif->tif_curstrip); return 0; error_code: + memset(op, 0, (size_t)occ); sp->read_error = 1; TIFFErrorExtR(tif, tif->tif_name, "Using code not yet in table"); return 0; @@ -800,7 +798,7 @@ error_code: static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) { static const char module[] = "LZWDecodeCompat"; - LZWCodecState *sp = DecoderState(tif); + LZWCodecState *sp = LZWDecoderState(tif); uint8_t *op = (uint8_t *)op0; tmsize_t occ = occ0; uint8_t *tp; @@ -1026,7 +1024,7 @@ static int LZWDecodeCompat(TIFF *tif, uint8_t *op0, tmsize_t occ0, uint16_t s) static int LZWSetupEncode(TIFF *tif) { static const char module[] = "LZWSetupEncode"; - LZWCodecState *sp = EncoderState(tif); + LZWCodecState *sp = LZWEncoderState(tif); assert(sp != NULL); sp->enc_hashtab = (hash_t *)_TIFFmallocExt(tif, HSIZE * sizeof(hash_t)); @@ -1043,7 +1041,7 @@ static int LZWSetupEncode(TIFF *tif) */ static int LZWPreEncode(TIFF *tif, uint16_t s) { - LZWCodecState *sp = EncoderState(tif); + LZWCodecState *sp = LZWEncoderState(tif); (void)s; assert(sp != NULL); @@ -1114,7 +1112,7 @@ static int LZWPreEncode(TIFF *tif, uint16_t s) */ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { - register LZWCodecState *sp = EncoderState(tif); + register LZWCodecState *sp = LZWEncoderState(tif); register long fcode; register hash_t *hp; register int h, c; @@ -1299,7 +1297,7 @@ static int LZWEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) */ static int LZWPostEncode(TIFF *tif) { - register LZWCodecState *sp = EncoderState(tif); + register LZWCodecState *sp = LZWEncoderState(tif); uint8_t *op = tif->tif_rawcp; long nextbits = sp->lzw_nextbits; WordType nextdata = sp->lzw_nextdata; @@ -1381,11 +1379,11 @@ static void LZWCleanup(TIFF *tif) assert(tif->tif_data != 0); - if (DecoderState(tif)->dec_codetab) - _TIFFfreeExt(tif, DecoderState(tif)->dec_codetab); + if (LZWDecoderState(tif)->dec_codetab) + _TIFFfreeExt(tif, LZWDecoderState(tif)->dec_codetab); - if (EncoderState(tif)->enc_hashtab) - _TIFFfreeExt(tif, EncoderState(tif)->enc_hashtab); + if (LZWEncoderState(tif)->enc_hashtab) + _TIFFfreeExt(tif, LZWEncoderState(tif)->enc_hashtab); _TIFFfreeExt(tif, tif->tif_data); tif->tif_data = NULL; @@ -1404,9 +1402,9 @@ int TIFFInitLZW(TIFF *tif, int scheme) tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(LZWCodecState)); if (tif->tif_data == NULL) goto bad; - DecoderState(tif)->dec_codetab = NULL; - DecoderState(tif)->dec_decode = NULL; - EncoderState(tif)->enc_hashtab = NULL; + LZWDecoderState(tif)->dec_codetab = NULL; + LZWDecoderState(tif)->dec_decode = NULL; + LZWEncoderState(tif)->enc_hashtab = NULL; LZWState(tif)->rw_mode = tif->tif_mode; /* diff --git a/3rdparty/libtiff/tif_ojpeg.c b/3rdparty/libtiff/tif_ojpeg.c index ea572091e5..f94d2a4e45 100644 --- a/3rdparty/libtiff/tif_ojpeg.c +++ b/3rdparty/libtiff/tif_ojpeg.c @@ -207,37 +207,21 @@ static const TIFFField ojpegFields[] = { #include #endif -/* We undefine FAR to avoid conflict with JPEG definition */ - -#ifdef FAR -#undef FAR -#endif - -/* - Libjpeg's jmorecfg.h defines INT16 and INT32, but only if XMD_H is - not defined. Unfortunately, the MinGW and Borland compilers include - a typedef for INT32, which causes a conflict. MSVC does not include - a conflicting typedef given the headers which are included. -*/ -#if defined(__BORLANDC__) || defined(__MINGW32__) -#define XMD_H 1 -#endif - -/* Define "boolean" as unsigned char, not int, per Windows custom. */ -#if defined(__WIN32__) && !defined(__MINGW32__) -#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ -typedef unsigned char boolean; -#endif -#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ -#endif - #include "jerror.h" #include "jpeglib.h" +#ifndef TIFF_jpeg_source_mgr_defined +#define TIFF_jpeg_source_mgr_defined +typedef struct jpeg_source_mgr jpeg_source_mgr; +#endif + +#ifndef TIFF_jpeg_error_mgr_defined +#define TIFF_jpeg_error_mgr_defined typedef struct jpeg_error_mgr jpeg_error_mgr; +#endif + typedef struct jpeg_common_struct jpeg_common_struct; typedef struct jpeg_decompress_struct jpeg_decompress_struct; -typedef struct jpeg_source_mgr jpeg_source_mgr; typedef enum { @@ -771,6 +755,9 @@ static int OJPEGPreDecode(TIFF *tif, uint16_t s) if (OJPEGWriteHeaderInfo(tif) == 0) return (0); } + + sp->subsampling_convert_state = 0; + while (sp->write_curstrile < m) { if (sp->libjpeg_jpeg_query_style == 0) @@ -856,12 +843,14 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) (void)s; if (!sp->decoder_ok) { + memset(buf, 0, (size_t)cc); TIFFErrorExtR(tif, module, "Cannot decode: decoder not correctly initialized"); return 0; } if (sp->libjpeg_session_active == 0) { + memset(buf, 0, (size_t)cc); /* This should normally not happen, except that it does when */ /* using TIFFReadScanline() which calls OJPEGPostDecode() for */ /* each scanline, which assumes that a whole strile was read */ @@ -875,17 +864,24 @@ static int OJPEGDecode(TIFF *tif, uint8_t *buf, tmsize_t cc, uint16_t s) } if (sp->error_in_raw_data_decoding) { + memset(buf, 0, (size_t)cc); return 0; } if (sp->libjpeg_jpeg_query_style == 0) { if (OJPEGDecodeRaw(tif, buf, cc) == 0) + { + memset(buf, 0, (size_t)cc); return (0); + } } else { if (OJPEGDecodeScanlines(tif, buf, cc) == 0) + { + memset(buf, 0, (size_t)cc); return (0); + } } return (1); } diff --git a/3rdparty/libtiff/tif_open.c b/3rdparty/libtiff/tif_open.c index 23fcf81c43..59a07bee02 100644 --- a/3rdparty/libtiff/tif_open.c +++ b/3rdparty/libtiff/tif_open.c @@ -25,7 +25,13 @@ /* * TIFF Library. */ + +#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#endif + #include "tiffiop.h" +#include #include /* @@ -81,8 +87,9 @@ TIFFOpenOptions *TIFFOpenOptionsAlloc() void TIFFOpenOptionsFree(TIFFOpenOptions *opts) { _TIFFfree(opts); } /** Define a limit in bytes for a single memory allocation done by libtiff. - * If max_single_mem_alloc is set to 0, no other limit that the underlying - * _TIFFmalloc() will be applied, which is the default. + * If max_single_mem_alloc is set to 0, which is the default, no other limit + * that the underlying _TIFFmalloc() or + * TIFFOpenOptionsSetMaxCumulatedMemAlloc() will be applied. */ void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts, tmsize_t max_single_mem_alloc) @@ -90,6 +97,18 @@ void TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts, opts->max_single_mem_alloc = max_single_mem_alloc; } +/** Define a limit in bytes for the cumulated memory allocations done by libtiff + * on a given TIFF handle. + * If max_cumulated_mem_alloc is set to 0, which is the default, no other limit + * that the underlying _TIFFmalloc() or + * TIFFOpenOptionsSetMaxSingleMemAlloc() will be applied. + */ +void TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts, + tmsize_t max_cumulated_mem_alloc) +{ + opts->max_cumulated_mem_alloc = max_cumulated_mem_alloc; +} + void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts, TIFFErrorHandlerExtR handler, void *errorhandler_user_data) @@ -117,6 +136,30 @@ static void _TIFFEmitErrorAboveMaxSingleMemAlloc(TIFF *tif, (uint64_t)s, (uint64_t)tif->tif_max_single_mem_alloc); } +static void _TIFFEmitErrorAboveMaxCumulatedMemAlloc(TIFF *tif, + const char *pszFunction, + tmsize_t s) +{ + TIFFErrorExtR(tif, pszFunction, + "Cumulated memory allocation of %" PRIu64 " + %" PRIu64 + " bytes is beyond the %" PRIu64 + " cumulated byte limit defined in open options", + (uint64_t)tif->tif_cur_cumulated_mem_alloc, (uint64_t)s, + (uint64_t)tif->tif_max_cumulated_mem_alloc); +} + +/* When allocating memory, we write at the beginning of the buffer it size. + * This allows us to keep track of the total memory allocated when we + * malloc/calloc/realloc and free. In theory we need just SIZEOF_SIZE_T bytes + * for that, but on x86_64, allocations of more than 16 bytes are aligned on + * 16 bytes. Hence using 2 * SIZEOF_SIZE_T. + * It is critical that _TIFFmallocExt/_TIFFcallocExt/_TIFFreallocExt are + * paired with _TIFFfreeExt. + * CMakeLists.txt defines TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS, which in + * turn disables the definition of the non Ext version in tiffio.h + */ +#define LEADING_AREA_TO_STORE_ALLOC_SIZE (2 * SIZEOF_SIZE_T) + /** malloc() version that takes into account memory-specific open options */ void *_TIFFmallocExt(TIFF *tif, tmsize_t s) { @@ -126,16 +169,32 @@ void *_TIFFmallocExt(TIFF *tif, tmsize_t s) _TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFmallocExt", s); return NULL; } + if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0) + { + if (s > tif->tif_max_cumulated_mem_alloc - + tif->tif_cur_cumulated_mem_alloc || + s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE) + { + _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFmallocExt", s); + return NULL; + } + void *ptr = _TIFFmalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s); + if (!ptr) + return NULL; + tif->tif_cur_cumulated_mem_alloc += s; + memcpy(ptr, &s, sizeof(s)); + return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE; + } return _TIFFmalloc(s); } /** calloc() version that takes into account memory-specific open options */ void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz) { + if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz) + return NULL; if (tif != NULL && tif->tif_max_single_mem_alloc > 0) { - if (nmemb <= 0 || siz <= 0 || nmemb > TIFF_TMSIZE_T_MAX / siz) - return NULL; if (nmemb * siz > tif->tif_max_single_mem_alloc) { _TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFcallocExt", @@ -143,6 +202,23 @@ void *_TIFFcallocExt(TIFF *tif, tmsize_t nmemb, tmsize_t siz) return NULL; } } + if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0) + { + const tmsize_t s = nmemb * siz; + if (s > tif->tif_max_cumulated_mem_alloc - + tif->tif_cur_cumulated_mem_alloc || + s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE) + { + _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFcallocExt", s); + return NULL; + } + void *ptr = _TIFFcalloc(LEADING_AREA_TO_STORE_ALLOC_SIZE + s, 1); + if (!ptr) + return NULL; + tif->tif_cur_cumulated_mem_alloc += s; + memcpy(ptr, &s, sizeof(s)); + return (char *)ptr + LEADING_AREA_TO_STORE_ALLOC_SIZE; + } return _TIFFcalloc(nmemb, siz); } @@ -155,13 +231,49 @@ void *_TIFFreallocExt(TIFF *tif, void *p, tmsize_t s) _TIFFEmitErrorAboveMaxSingleMemAlloc(tif, "_TIFFreallocExt", s); return NULL; } + if (tif != NULL && tif->tif_max_cumulated_mem_alloc > 0) + { + void *oldPtr = p; + tmsize_t oldSize = 0; + if (p) + { + oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE; + memcpy(&oldSize, oldPtr, sizeof(oldSize)); + assert(oldSize <= tif->tif_cur_cumulated_mem_alloc); + } + if (s > oldSize && + (s > tif->tif_max_cumulated_mem_alloc - + (tif->tif_cur_cumulated_mem_alloc - oldSize) || + s > TIFF_TMSIZE_T_MAX - LEADING_AREA_TO_STORE_ALLOC_SIZE)) + { + _TIFFEmitErrorAboveMaxCumulatedMemAlloc(tif, "_TIFFreallocExt", + s - oldSize); + return NULL; + } + void *newPtr = + _TIFFrealloc(oldPtr, LEADING_AREA_TO_STORE_ALLOC_SIZE + s); + if (newPtr == NULL) + return NULL; + tif->tif_cur_cumulated_mem_alloc -= oldSize; + tif->tif_cur_cumulated_mem_alloc += s; + memcpy(newPtr, &s, sizeof(s)); + return (char *)newPtr + LEADING_AREA_TO_STORE_ALLOC_SIZE; + } return _TIFFrealloc(p, s); } /** free() version that takes into account memory-specific open options */ void _TIFFfreeExt(TIFF *tif, void *p) { - (void)tif; + if (p != NULL && tif != NULL && tif->tif_max_cumulated_mem_alloc > 0) + { + void *oldPtr = (char *)p - LEADING_AREA_TO_STORE_ALLOC_SIZE; + tmsize_t oldSize; + memcpy(&oldSize, oldPtr, sizeof(oldSize)); + assert(oldSize <= tif->tif_cur_cumulated_mem_alloc); + tif->tif_cur_cumulated_mem_alloc -= oldSize; + p = oldPtr; + } _TIFFfree(p); } @@ -231,6 +343,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, (uint64_t)opts->max_single_mem_alloc); goto bad2; } + if (opts && opts->max_cumulated_mem_alloc > 0 && + size_to_alloc > opts->max_cumulated_mem_alloc) + { + _TIFFErrorEarly(opts, clientdata, module, + "%s: Memory allocation of %" PRIu64 + " bytes is beyond the %" PRIu64 + " cumulated byte limit defined in open options", + name, (uint64_t)size_to_alloc, + (uint64_t)opts->max_cumulated_mem_alloc); + goto bad2; + } tif = (TIFF *)_TIFFmallocExt(NULL, size_to_alloc); if (tif == NULL) { @@ -243,6 +366,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, strcpy(tif->tif_name, name); tif->tif_mode = m & ~(O_CREAT | O_TRUNC); tif->tif_curdir = TIFF_NON_EXISTENT_DIR_NUMBER; /* non-existent directory */ + tif->tif_curdircount = TIFF_NON_EXISTENT_DIR_NUMBER; tif->tif_curoff = 0; tif->tif_curstrip = (uint32_t)-1; /* invalid strip */ tif->tif_row = (uint32_t)-1; /* read/write pre-increment */ @@ -261,6 +385,7 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, tif->tif_warnhandler = opts->warnhandler; tif->tif_warnhandler_user_data = opts->warnhandler_user_data; tif->tif_max_single_mem_alloc = opts->max_single_mem_alloc; + tif->tif_max_cumulated_mem_alloc = opts->max_cumulated_mem_alloc; } if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) @@ -423,9 +548,9 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, TIFFErrorExtR(tif, name, "Cannot read TIFF header"); goto bad; } -/* - * Setup header and write. - */ + /* + * Setup header and write. + */ #ifdef WORDS_BIGENDIAN tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN; @@ -433,13 +558,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, tif->tif_header.common.tiff_magic = (tif->tif_flags & TIFF_SWAB) ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN; #endif + TIFFHeaderUnion tif_header_swapped; if (!(tif->tif_flags & TIFF_BIGTIFF)) { tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC; tif->tif_header.classic.tiff_diroff = 0; - if (tif->tif_flags & TIFF_SWAB) - TIFFSwabShort(&tif->tif_header.common.tiff_version); tif->tif_header_size = sizeof(TIFFHeaderClassic); + /* Swapped copy for writing */ + _TIFFmemcpy(&tif_header_swapped, &tif->tif_header, + sizeof(TIFFHeaderUnion)); + if (tif->tif_flags & TIFF_SWAB) + TIFFSwabShort(&tif_header_swapped.common.tiff_version); } else { @@ -447,12 +576,15 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, tif->tif_header.big.tiff_offsetsize = 8; tif->tif_header.big.tiff_unused = 0; tif->tif_header.big.tiff_diroff = 0; + tif->tif_header_size = sizeof(TIFFHeaderBig); + /* Swapped copy for writing */ + _TIFFmemcpy(&tif_header_swapped, &tif->tif_header, + sizeof(TIFFHeaderUnion)); if (tif->tif_flags & TIFF_SWAB) { - TIFFSwabShort(&tif->tif_header.common.tiff_version); - TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize); + TIFFSwabShort(&tif_header_swapped.common.tiff_version); + TIFFSwabShort(&tif_header_swapped.big.tiff_offsetsize); } - tif->tif_header_size = sizeof(TIFFHeaderBig); } /* * The doc for "fopen" for some STD_C_LIBs says that if you @@ -462,26 +594,12 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, * on Solaris. */ TIFFSeekFile(tif, 0, SEEK_SET); - if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) + if (!WriteOK(tif, &tif_header_swapped, + (tmsize_t)(tif->tif_header_size))) { TIFFErrorExtR(tif, name, "Error writing TIFF header"); goto bad; } - /* - * Setup the byte order handling. - */ - if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) - { -#ifndef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; -#endif - } - else - { -#ifdef WORDS_BIGENDIAN - tif->tif_flags |= TIFF_SWAB; -#endif - } /* * Setup default directory. */ @@ -490,10 +608,14 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, tif->tif_diroff = 0; tif->tif_lastdiroff = 0; tif->tif_setdirectory_force_absolute = FALSE; + /* tif_curdircount = 0 means 'empty file opened for writing, but no IFD + * written yet' */ + tif->tif_curdircount = 0; return (tif); } + /* - * Setup the byte order handling. + * Setup the byte order handling according to the opened file for reading. */ if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN && tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN @@ -619,9 +741,17 @@ TIFF *TIFFClientOpenExt(const char *name, const char *mode, * example, it may be broken) and want to proceed to other * directories. I this case we use the TIFF_HEADERONLY flag to open * file and return immediately after reading TIFF header. + * However, the pointer to TIFFSetField() and TIFFGetField() + * (i.e. tif->tif_tagmethods.vsetfield and + * tif->tif_tagmethods.vgetfield) need to be initialized, which is + * done in TIFFDefaultDirectory(). */ if (tif->tif_flags & TIFF_HEADERONLY) + { + if (!TIFFDefaultDirectory(tif)) + goto bad; return (tif); + } /* * Setup initial directory. @@ -764,10 +894,7 @@ int TIFFIsBigEndian(TIFF *tif) /* * Return nonzero if given file is BigTIFF style. */ -int TIFFIsBigTIFF(TIFF *tif) -{ - return (tif->tif_header.common.tiff_version == TIFF_VERSION_BIG); -} +int TIFFIsBigTIFF(TIFF *tif) { return ((tif->tif_flags & TIFF_BIGTIFF) != 0); } /* * Return pointer to file read method. diff --git a/3rdparty/libtiff/tif_packbits.c b/3rdparty/libtiff/tif_packbits.c index 62849f8f3c..1ae50cbd47 100644 --- a/3rdparty/libtiff/tif_packbits.c +++ b/3rdparty/libtiff/tif_packbits.c @@ -300,6 +300,7 @@ static int PackBitsDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) tif->tif_rawcc = cc; if (occ > 0) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Not enough data for scanline %" PRIu32, tif->tif_row); return (0); diff --git a/3rdparty/libtiff/tif_pixarlog.c b/3rdparty/libtiff/tif_pixarlog.c index 5c0346b6ec..56cf416a7f 100644 --- a/3rdparty/libtiff/tif_pixarlog.c +++ b/3rdparty/libtiff/tif_pixarlog.c @@ -670,8 +670,8 @@ static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp) return 1; } -#define DecoderState(tif) ((PixarLogState *)(tif)->tif_data) -#define EncoderState(tif) ((PixarLogState *)(tif)->tif_data) +#define PixarLogDecoderState(tif) ((PixarLogState *)(tif)->tif_data) +#define PixarLogEncoderState(tif) ((PixarLogState *)(tif)->tif_data) static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); @@ -740,7 +740,7 @@ static int PixarLogSetupDecode(TIFF *tif) { static const char module[] = "PixarLogSetupDecode"; TIFFDirectory *td = &tif->tif_dir; - PixarLogState *sp = DecoderState(tif); + PixarLogState *sp = PixarLogDecoderState(tif); tmsize_t tbuf_size; uint32_t strip_height; @@ -813,7 +813,7 @@ static int PixarLogSetupDecode(TIFF *tif) static int PixarLogPreDecode(TIFF *tif, uint16_t s) { static const char module[] = "PixarLogPreDecode"; - PixarLogState *sp = DecoderState(tif); + PixarLogState *sp = PixarLogDecoderState(tif); (void)s; assert(sp != NULL); @@ -835,7 +835,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { static const char module[] = "PixarLogDecode"; TIFFDirectory *td = &tif->tif_dir; - PixarLogState *sp = DecoderState(tif); + PixarLogState *sp = PixarLogDecoderState(tif); tmsize_t i; tmsize_t nsamples; int llen; @@ -859,6 +859,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) TIFFErrorExtR(tif, module, "%" PRIu16 " bit input not supported in PixarLog", td->td_bitspersample); + memset(op, 0, (size_t)occ); return 0; } @@ -879,12 +880,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->stream.avail_out != nsamples * sizeof(uint16_t)) { TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size"); + memset(op, 0, (size_t)occ); return (0); } /* Check that we will not fill more than what was allocated */ if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size) { TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size"); + memset(op, 0, (size_t)occ); return (0); } do @@ -899,12 +902,14 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) TIFFErrorExtR( tif, module, "Decoding error at scanline %" PRIu32 ", %s", tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); + memset(op, 0, (size_t)occ); return (0); } if (state != Z_OK) { TIFFErrorExtR(tif, module, "ZLib error: %s", sp->stream.msg ? sp->stream.msg : "(null)"); + memset(op, 0, (size_t)occ); return (0); } } while (sp->stream.avail_out > 0); @@ -916,6 +921,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) "Not enough data at scanline %" PRIu32 " (short %u bytes)", tif->tif_row, sp->stream.avail_out); + memset(op, 0, (size_t)occ); return (0); } @@ -977,6 +983,7 @@ static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) default: TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16, td->td_bitspersample); + memset(op, 0, (size_t)occ); return (0); } } @@ -988,7 +995,7 @@ static int PixarLogSetupEncode(TIFF *tif) { static const char module[] = "PixarLogSetupEncode"; TIFFDirectory *td = &tif->tif_dir; - PixarLogState *sp = EncoderState(tif); + PixarLogState *sp = PixarLogEncoderState(tif); tmsize_t tbuf_size; assert(sp != NULL); @@ -1038,7 +1045,7 @@ static int PixarLogSetupEncode(TIFF *tif) static int PixarLogPreEncode(TIFF *tif, uint16_t s) { static const char module[] = "PixarLogPreEncode"; - PixarLogState *sp = EncoderState(tif); + PixarLogState *sp = PixarLogEncoderState(tif); (void)s; assert(sp != NULL); @@ -1294,7 +1301,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { static const char module[] = "PixarLogEncode"; TIFFDirectory *td = &tif->tif_dir; - PixarLogState *sp = EncoderState(tif); + PixarLogState *sp = PixarLogEncoderState(tif); tmsize_t i; tmsize_t n; int llen; @@ -1401,7 +1408,7 @@ static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) static int PixarLogPostEncode(TIFF *tif) { static const char module[] = "PixarLogPostEncode"; - PixarLogState *sp = EncoderState(tif); + PixarLogState *sp = PixarLogEncoderState(tif); int state; sp->stream.avail_in = 0; diff --git a/3rdparty/libtiff/tif_read.c b/3rdparty/libtiff/tif_read.c index 4fec83969e..7efab59c6a 100644 --- a/3rdparty/libtiff/tif_read.c +++ b/3rdparty/libtiff/tif_read.c @@ -105,8 +105,8 @@ static int TIFFReadAndRealloc(TIFF *tif, tmsize_t size, tmsize_t rawdata_offset, TIFFErrorExtR(tif, module, "Invalid buffer size"); return 0; } - new_rawdata = - (uint8_t *)_TIFFrealloc(tif->tif_rawdata, tif->tif_rawdatasize); + new_rawdata = (uint8_t *)_TIFFreallocExt(tif, tif->tif_rawdata, + tif->tif_rawdatasize); if (new_rawdata == 0) { TIFFErrorExtR(tif, module, @@ -464,6 +464,10 @@ int TIFFReadScanline(TIFF *tif, void *buf, uint32_t row, uint16_t sample) if (e) (*tif->tif_postdecode)(tif, (uint8_t *)buf, tif->tif_scanlinesize); } + else + { + memset(buf, 0, (size_t)tif->tif_scanlinesize); + } return (e > 0 ? 1 : -1); } @@ -495,6 +499,11 @@ static tmsize_t TIFFReadEncodedStripGetStripSize(TIFF *tif, uint32_t strip, rowsperstrip = td->td_rowsperstrip; if (rowsperstrip > td->td_imagelength) rowsperstrip = td->td_imagelength; + if (rowsperstrip == 0) + { + TIFFErrorExtR(tif, module, "rowsperstrip is zero"); + return ((tmsize_t)(-1)); + } stripsperplane = TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); stripinplane = (strip % stripsperplane); @@ -544,7 +553,10 @@ tmsize_t TIFFReadEncodedStrip(TIFF *tif, uint32_t strip, void *buf, if ((size != (tmsize_t)(-1)) && (size < stripsize)) stripsize = size; if (!TIFFFillStrip(tif, strip)) + { + memset(buf, 0, (size_t)stripsize); return ((tmsize_t)(-1)); + } if ((*tif->tif_decodestrip)(tif, buf, stripsize, plane) <= 0) return ((tmsize_t)(-1)); (*tif->tif_postdecode)(tif, buf, stripsize); @@ -962,9 +974,13 @@ tmsize_t TIFFReadEncodedTile(TIFF *tif, uint32_t tile, void *buf, tmsize_t size) size = tilesize; else if (size > tilesize) size = tilesize; - if (TIFFFillTile(tif, tile) && - (*tif->tif_decodetile)(tif, (uint8_t *)buf, size, - (uint16_t)(tile / td->td_stripsperimage))) + if (!TIFFFillTile(tif, tile)) + { + memset(buf, 0, (size_t)size); + return ((tmsize_t)(-1)); + } + else if ((*tif->tif_decodetile)(tif, (uint8_t *)buf, size, + (uint16_t)(tile / td->td_stripsperimage))) { (*tif->tif_postdecode)(tif, (uint8_t *)buf, size); return (size); @@ -1449,6 +1465,11 @@ static int TIFFStartTile(TIFF *tif, uint32_t tile) tif->tif_flags |= TIFF_CODERSETUP; } tif->tif_curtile = tile; + if (td->td_tilewidth == 0) + { + TIFFErrorExtR(tif, module, "Zero tilewidth"); + return 0; + } howmany32 = TIFFhowmany_32(td->td_imagewidth, td->td_tilewidth); if (howmany32 == 0) { @@ -1545,9 +1566,14 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf, if (TIFFIsTiled(tif)) { - if (!TIFFStartTile(tif, strile) || - !(*tif->tif_decodetile)(tif, (uint8_t *)outbuf, outsize, - (uint16_t)(strile / td->td_stripsperimage))) + if (!TIFFStartTile(tif, strile)) + { + ret = 0; + memset(outbuf, 0, (size_t)outsize); + } + else if (!(*tif->tif_decodetile)( + tif, (uint8_t *)outbuf, outsize, + (uint16_t)(strile / td->td_stripsperimage))) { ret = 0; } @@ -1558,14 +1584,27 @@ int TIFFReadFromUserBuffer(TIFF *tif, uint32_t strile, void *inbuf, uint32_t stripsperplane; if (rowsperstrip > td->td_imagelength) rowsperstrip = td->td_imagelength; - stripsperplane = - TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); - if (!TIFFStartStrip(tif, strile) || - !(*tif->tif_decodestrip)(tif, (uint8_t *)outbuf, outsize, - (uint16_t)(strile / stripsperplane))) + if (rowsperstrip == 0) { + TIFFErrorExtR(tif, module, "rowsperstrip is zero"); ret = 0; } + else + { + stripsperplane = + TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip); + if (!TIFFStartStrip(tif, strile)) + { + ret = 0; + memset(outbuf, 0, (size_t)outsize); + } + else if (!(*tif->tif_decodestrip)( + tif, (uint8_t *)outbuf, outsize, + (uint16_t)(strile / stripsperplane))) + { + ret = 0; + } + } } if (ret) { diff --git a/3rdparty/libtiff/tif_strip.c b/3rdparty/libtiff/tif_strip.c index 820a2544c3..4dbcf37e48 100644 --- a/3rdparty/libtiff/tif_strip.c +++ b/3rdparty/libtiff/tif_strip.c @@ -38,6 +38,11 @@ uint32_t TIFFComputeStrip(TIFF *tif, uint32_t row, uint16_t sample) TIFFDirectory *td = &tif->tif_dir; uint32_t strip; + if (td->td_rowsperstrip == 0) + { + TIFFErrorExtR(tif, module, "Cannot compute strip: RowsPerStrip is zero"); + return 0; + } strip = row / td->td_rowsperstrip; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) { @@ -61,6 +66,11 @@ uint32_t TIFFNumberOfStrips(TIFF *tif) TIFFDirectory *td = &tif->tif_dir; uint32_t nstrips; + if (td->td_rowsperstrip == 0) + { + TIFFWarningExtR(tif, "TIFFNumberOfStrips", "RowsPerStrip is zero"); + return 0; + } nstrips = (td->td_rowsperstrip == (uint32_t)-1 ? 1 : TIFFhowmany_32(td->td_imagelength, td->td_rowsperstrip)); @@ -107,7 +117,8 @@ uint64_t TIFFVStripSize64(TIFF *tif, uint32_t nrows) if ((ycbcrsubsampling[0] != 1 && ycbcrsubsampling[0] != 2 && ycbcrsubsampling[0] != 4) || (ycbcrsubsampling[1] != 1 && ycbcrsubsampling[1] != 2 && - ycbcrsubsampling[1] != 4)) + ycbcrsubsampling[1] != 4) || + (ycbcrsubsampling[0] == 0 || ycbcrsubsampling[1] == 0)) { TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling (%dx%d)", ycbcrsubsampling[0], ycbcrsubsampling[1]); @@ -267,7 +278,8 @@ uint64_t TIFFScanlineSize64(TIFF *tif) if (((ycbcrsubsampling[0] != 1) && (ycbcrsubsampling[0] != 2) && (ycbcrsubsampling[0] != 4)) || ((ycbcrsubsampling[1] != 1) && (ycbcrsubsampling[1] != 2) && - (ycbcrsubsampling[1] != 4))) + (ycbcrsubsampling[1] != 4)) || + ((ycbcrsubsampling[0] == 0) || (ycbcrsubsampling[1] == 0))) { TIFFErrorExtR(tif, module, "Invalid YCbCr subsampling"); return 0; @@ -287,7 +299,25 @@ uint64_t TIFFScanlineSize64(TIFF *tif) else { uint64_t scanline_samples; - scanline_samples = _TIFFMultiply64(tif, td->td_imagewidth, + uint32_t scanline_width = td->td_imagewidth; + +#if 0 + // Tries to fix https://gitlab.com/libtiff/libtiff/-/merge_requests/564 + // but causes regression when decoding legit files with tiffcp -c none + // Cf https://gitlab.com/libtiff/libtiff/-/merge_requests/644 + if (td->td_photometric == PHOTOMETRIC_YCBCR) + { + uint16_t subsampling_hor; + uint16_t ignored; + TIFFGetFieldDefaulted(tif, TIFFTAG_YCBCRSUBSAMPLING, + &subsampling_hor, &ignored); + if (subsampling_hor > 1) // roundup width for YCbCr + scanline_width = + TIFFroundup_32(scanline_width, subsampling_hor); + } +#endif + + scanline_samples = _TIFFMultiply64(tif, scanline_width, td->td_samplesperpixel, module); scanline_size = TIFFhowmany_64(_TIFFMultiply64(tif, scanline_samples, diff --git a/3rdparty/libtiff/tif_thunder.c b/3rdparty/libtiff/tif_thunder.c index 1f97362ca3..bac0607dbe 100644 --- a/3rdparty/libtiff/tif_thunder.c +++ b/3rdparty/libtiff/tif_thunder.c @@ -82,13 +82,14 @@ static int ThunderSetupDecode(TIFF *tif) return (1); } -static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) +static int ThunderDecode(TIFF *tif, uint8_t *op0, tmsize_t maxpixels) { static const char module[] = "ThunderDecode"; register unsigned char *bp; register tmsize_t cc; unsigned int lastpixel; tmsize_t npixels; + uint8_t *op = op0; bp = (unsigned char *)tif->tif_rawcp; cc = tif->tif_rawcc; @@ -107,6 +108,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) * Replicate the last pixel n times, * where n is the lower-order 6 bits. */ + if (n == 0) + break; if (npixels & 1) { op[0] |= lastpixel; @@ -117,11 +120,10 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) else lastpixel |= lastpixel << 4; npixels += n; - if (npixels < maxpixels) - { - for (; n > 0; n -= 2) - *op++ = (uint8_t)lastpixel; - } + if (npixels > maxpixels) + break; + for (; n > 0; n -= 2) + *op++ = (uint8_t)lastpixel; if (n == -1) *--op &= 0xf0; lastpixel &= 0xf; @@ -154,6 +156,8 @@ static int ThunderDecode(TIFF *tif, uint8_t *op, tmsize_t maxpixels) tif->tif_rawcc = cc; if (npixels != maxpixels) { + uint8_t *op_end = op0 + (maxpixels + 1) / 2; + memset(op, 0, (size_t)(op_end - op)); TIFFErrorExtR(tif, module, "%s data at scanline %lu (%" PRIu64 " != %" PRIu64 ")", npixels < maxpixels ? "Not enough" : "Too much", diff --git a/3rdparty/libtiff/tif_unix.c b/3rdparty/libtiff/tif_unix.c index 34dd53b98c..e65da872a3 100644 --- a/3rdparty/libtiff/tif_unix.c +++ b/3rdparty/libtiff/tif_unix.c @@ -27,6 +27,10 @@ * Windows Common RunTime Library. */ +#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#endif + #include "tif_config.h" #ifdef HAVE_SYS_TYPES_H @@ -79,6 +83,8 @@ static tmsize_t _tiffReadProc(thandle_t fd, void *buf, tmsize_t size) size_t io_size = bytes_total - bytes_read; if (io_size > TIFF_IO_MAX) io_size = TIFF_IO_MAX; + /* Below is an obvious false positive of Coverity Scan */ + /* coverity[overflow_sink] */ count = read(fdh.fd, buf_offset, (TIFFIOSize_t)io_size); if (count <= 0) break; @@ -106,6 +112,8 @@ static tmsize_t _tiffWriteProc(thandle_t fd, void *buf, tmsize_t size) size_t io_size = bytes_total - bytes_written; if (io_size > TIFF_IO_MAX) io_size = TIFF_IO_MAX; + /* Below is an obvious false positive of Coverity Scan */ + /* coverity[overflow_sink] */ count = write(fdh.fd, buf_offset, (TIFFIOSize_t)io_size); if (count <= 0) break; @@ -258,7 +266,7 @@ TIFF *TIFFOpenExt(const char *name, const char *mode, TIFFOpenOptions *opts) return tif; } -#ifdef __WIN32__ +#ifdef _WIN32 #include /* * Open a TIFF file with a Unicode filename, for read/writing. diff --git a/3rdparty/libtiff/tif_webp.c b/3rdparty/libtiff/tif_webp.c index bf9d77eb9b..ccffef0703 100644 --- a/3rdparty/libtiff/tif_webp.c +++ b/3rdparty/libtiff/tif_webp.c @@ -47,7 +47,9 @@ typedef struct { uint16_t nSamples; /* number of samples per pixel */ - int lossless; /* lossy/lossless compression */ + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ + int lossless; /* lossy/lossless compression */ int lossless_exact; /* lossless exact mode. If TRUE, R,G,B values in areas with alpha = 0 will be preserved */ int quality_level; /* compression level */ @@ -133,6 +135,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) assert(sp != NULL); assert(sp->state == LSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "ZIPDecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + if (sp->psDecoder == NULL) { TIFFDirectory *td = &tif->tif_dir; @@ -158,12 +170,16 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) : (uint32_t)tif->tif_rawcc, &webp_width, &webp_height)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPGetInfo() failed"); return 0; } if ((uint32_t)webp_width != segment_width || (uint32_t)webp_height != segment_height) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR( tif, module, "WebP blob dimension is %dx%d. Expected %ux%u", webp_width, webp_height, segment_width, segment_height); @@ -174,6 +190,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) WebPDecoderConfig config; if (!WebPInitDecoderConfig(&config)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); return 0; } @@ -189,6 +207,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (!bWebPGetFeaturesOK) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebPInitDecoderConfig() failed"); return 0; } @@ -202,6 +222,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) */ !(webp_bands == 3 && sp->nSamples == 4)) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "WebP blob band count is %d. Expected %d", webp_bands, sp->nSamples); @@ -228,6 +250,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (!sp->pBuffer) { TIFFErrorExtR(tif, module, "Cannot allocate buffer"); + memset(op, 0, (size_t)occ); + sp->read_error = 1; return 0; } sp->buffer_size = buffer_size; @@ -257,6 +281,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (sp->psDecoder == NULL) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to allocate WebP decoder."); return 0; } @@ -264,6 +290,10 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (occ % sp->sDecBuffer.u.RGBA.stride) { + // read_error not set here as this is a usage issue that can be + // recovered in a following call. + memset(op, 0, (size_t)occ); + /* Do not set read_error as could potentially be recovered */ TIFFErrorExtR(tif, module, "Fractional scanlines cannot be read"); return 0; } @@ -284,6 +314,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { TIFFErrorExtR(tif, module, "Unrecognized error."); } + memset(op, 0, (size_t)occ); + sp->read_error = 1; return 0; } else @@ -303,6 +335,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { if (current_y != numberOfExpectedLines) { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to decode WebP data: less lines than " "expected."); @@ -332,6 +366,8 @@ static int TWebPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) } else { + memset(op, 0, (size_t)occ); + sp->read_error = 1; TIFFErrorExtR(tif, module, "Unable to decode WebP data."); return 0; } @@ -451,6 +487,8 @@ static int TWebPPreDecode(TIFF *tif, uint16_t s) sp->psDecoder = NULL; } + sp->read_error = 0; + return 1; } diff --git a/3rdparty/libtiff/tif_win32.c b/3rdparty/libtiff/tif_win32.c index 1a6b86dffb..d64ba49f0e 100644 --- a/3rdparty/libtiff/tif_win32.c +++ b/3rdparty/libtiff/tif_win32.c @@ -27,6 +27,10 @@ * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA */ +#ifdef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#undef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS +#endif + #include "tiffiop.h" #include diff --git a/3rdparty/libtiff/tif_zip.c b/3rdparty/libtiff/tif_zip.c index fcf510044c..2a2a1d787f 100644 --- a/3rdparty/libtiff/tif_zip.c +++ b/3rdparty/libtiff/tif_zip.c @@ -67,6 +67,8 @@ typedef struct { TIFFPredictorState predict; z_stream stream; + int read_error; /* whether a read error has occurred, and which should cause + further reads in the same strip/tile to be aborted */ int zipquality; /* compression level */ int state; /* state flags */ int subcodec; /* DEFLATE_SUBCODEC_ZLIB or DEFLATE_SUBCODEC_LIBDEFLATE */ @@ -83,9 +85,9 @@ typedef struct TIFFVSetMethod vsetparent; /* super-class method */ } ZIPState; -#define ZState(tif) ((ZIPState *)(tif)->tif_data) -#define DecoderState(tif) ZState(tif) -#define EncoderState(tif) ZState(tif) +#define GetZIPState(tif) ((ZIPState *)(tif)->tif_data) +#define ZIPDecoderState(tif) GetZIPState(tif) +#define ZIPEncoderState(tif) GetZIPState(tif) static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); @@ -99,7 +101,7 @@ static int ZIPFixupTags(TIFF *tif) static int ZIPSetupDecode(TIFF *tif) { static const char module[] = "ZIPSetupDecode"; - ZIPState *sp = DecoderState(tif); + ZIPState *sp = ZIPDecoderState(tif); assert(sp != NULL); @@ -131,7 +133,7 @@ static int ZIPSetupDecode(TIFF *tif) */ static int ZIPPreDecode(TIFF *tif, uint16_t s) { - ZIPState *sp = DecoderState(tif); + ZIPState *sp = ZIPDecoderState(tif); (void)s; assert(sp != NULL); @@ -150,18 +152,33 @@ static int ZIPPreDecode(TIFF *tif, uint16_t s) sp->stream.avail_in = (uint64_t)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU; - return (inflateReset(&sp->stream) == Z_OK); + if (inflateReset(&sp->stream) == Z_OK) + { + sp->read_error = 0; + return 1; + } + return 0; } static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { static const char module[] = "ZIPDecode"; - ZIPState *sp = DecoderState(tif); + ZIPState *sp = ZIPDecoderState(tif); (void)s; assert(sp != NULL); assert(sp->state == ZSTATE_INIT_DECODE); + if (sp->read_error) + { + memset(op, 0, (size_t)occ); + TIFFErrorExtR(tif, module, + "ZIPDecode: Scanline %" PRIu32 " cannot be read due to " + "previous error", + tif->tif_row); + return 0; + } + #if LIBDEFLATE_SUPPORT if (sp->libdeflate_state == 1) return 0; @@ -227,8 +244,10 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (res != LIBDEFLATE_SUCCESS && res != LIBDEFLATE_INSUFFICIENT_SPACE) { + memset(op, 0, (size_t)occ); TIFFErrorExtR(tif, module, "Decoding error at scanline %lu", (unsigned long)tif->tif_row); + sp->read_error = 1; return 0; } @@ -263,13 +282,17 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) break; if (state == Z_DATA_ERROR) { + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s", (unsigned long)tif->tif_row, SAFE_MSG(sp)); + sp->read_error = 1; return (0); } if (state != Z_OK) { + memset(sp->stream.next_out, 0, sp->stream.avail_out); TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp)); + sp->read_error = 1; return (0); } } while (occ > 0); @@ -279,6 +302,8 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) "Not enough data at scanline %lu (short %" PRIu64 " bytes)", (unsigned long)tif->tif_row, (uint64_t)occ); + memset(sp->stream.next_out, 0, sp->stream.avail_out); + sp->read_error = 1; return (0); } @@ -290,7 +315,7 @@ static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) static int ZIPSetupEncode(TIFF *tif) { static const char module[] = "ZIPSetupEncode"; - ZIPState *sp = EncoderState(tif); + ZIPState *sp = ZIPEncoderState(tif); int cappedQuality; assert(sp != NULL); @@ -321,7 +346,7 @@ static int ZIPSetupEncode(TIFF *tif) */ static int ZIPPreEncode(TIFF *tif, uint16_t s) { - ZIPState *sp = EncoderState(tif); + ZIPState *sp = ZIPEncoderState(tif); (void)s; assert(sp != NULL); @@ -348,7 +373,7 @@ static int ZIPPreEncode(TIFF *tif, uint16_t s) static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { static const char module[] = "ZIPEncode"; - ZIPState *sp = EncoderState(tif); + ZIPState *sp = ZIPEncoderState(tif); assert(sp != NULL); assert(sp->state == ZSTATE_INIT_ENCODE); @@ -487,7 +512,7 @@ static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) static int ZIPPostEncode(TIFF *tif) { static const char module[] = "ZIPPostEncode"; - ZIPState *sp = EncoderState(tif); + ZIPState *sp = ZIPEncoderState(tif); int state; #if LIBDEFLATE_SUPPORT @@ -526,7 +551,7 @@ static int ZIPPostEncode(TIFF *tif) static void ZIPCleanup(TIFF *tif) { - ZIPState *sp = ZState(tif); + ZIPState *sp = GetZIPState(tif); assert(sp != 0); @@ -562,7 +587,7 @@ static void ZIPCleanup(TIFF *tif) static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap) { static const char module[] = "ZIPVSetField"; - ZIPState *sp = ZState(tif); + ZIPState *sp = GetZIPState(tif); switch (tag) { @@ -628,7 +653,7 @@ static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap) static int ZIPVGetField(TIFF *tif, uint32_t tag, va_list ap) { - ZIPState *sp = ZState(tif); + ZIPState *sp = GetZIPState(tif); switch (tag) { @@ -680,7 +705,7 @@ int TIFFInitZIP(TIFF *tif, int scheme) tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, sizeof(ZIPState), 1); if (tif->tif_data == NULL) goto bad; - sp = ZState(tif); + sp = GetZIPState(tif); sp->stream.zalloc = NULL; sp->stream.zfree = NULL; sp->stream.opaque = NULL; diff --git a/3rdparty/libtiff/tif_zstd.c b/3rdparty/libtiff/tif_zstd.c index 646993103d..fc73ce9cf5 100644 --- a/3rdparty/libtiff/tif_zstd.c +++ b/3rdparty/libtiff/tif_zstd.c @@ -54,9 +54,9 @@ typedef struct TIFFVSetMethod vsetparent; /* super-class method */ } ZSTDState; -#define LState(tif) ((ZSTDState *)(tif)->tif_data) -#define DecoderState(tif) LState(tif) -#define EncoderState(tif) LState(tif) +#define GetZSTDState(tif) ((ZSTDState *)(tif)->tif_data) +#define ZSTDDecoderState(tif) GetZSTDState(tif) +#define ZSTDEncoderState(tif) GetZSTDState(tif) static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s); static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s); @@ -69,7 +69,7 @@ static int ZSTDFixupTags(TIFF *tif) static int ZSTDSetupDecode(TIFF *tif) { - ZSTDState *sp = DecoderState(tif); + ZSTDState *sp = ZSTDDecoderState(tif); assert(sp != NULL); @@ -91,7 +91,7 @@ static int ZSTDSetupDecode(TIFF *tif) static int ZSTDPreDecode(TIFF *tif, uint16_t s) { static const char module[] = "ZSTDPreDecode"; - ZSTDState *sp = DecoderState(tif); + ZSTDState *sp = ZSTDDecoderState(tif); size_t zstd_ret; (void)s; @@ -124,7 +124,7 @@ static int ZSTDPreDecode(TIFF *tif, uint16_t s) static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) { static const char module[] = "ZSTDDecode"; - ZSTDState *sp = DecoderState(tif); + ZSTDState *sp = ZSTDDecoderState(tif); ZSTD_inBuffer in_buffer; ZSTD_outBuffer out_buffer; size_t zstd_ret; @@ -146,6 +146,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) zstd_ret = ZSTD_decompressStream(sp->dstream, &out_buffer, &in_buffer); if (ZSTD_isError(zstd_ret)) { + memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos); TIFFErrorExtR(tif, module, "Error in ZSTD_decompressStream(): %s", ZSTD_getErrorName(zstd_ret)); return 0; @@ -155,6 +156,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) if (out_buffer.pos < (size_t)occ) { + memset(op + out_buffer.pos, 0, out_buffer.size - out_buffer.pos); TIFFErrorExtR(tif, module, "Not enough data at scanline %lu (short %lu bytes)", (unsigned long)tif->tif_row, @@ -170,7 +172,7 @@ static int ZSTDDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s) static int ZSTDSetupEncode(TIFF *tif) { - ZSTDState *sp = EncoderState(tif); + ZSTDState *sp = ZSTDEncoderState(tif); assert(sp != NULL); if (sp->state & LSTATE_INIT_DECODE) @@ -190,7 +192,7 @@ static int ZSTDSetupEncode(TIFF *tif) static int ZSTDPreEncode(TIFF *tif, uint16_t s) { static const char module[] = "ZSTDPreEncode"; - ZSTDState *sp = EncoderState(tif); + ZSTDState *sp = ZSTDEncoderState(tif); size_t zstd_ret; (void)s; @@ -229,7 +231,7 @@ static int ZSTDPreEncode(TIFF *tif, uint16_t s) static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) { static const char module[] = "ZSTDEncode"; - ZSTDState *sp = EncoderState(tif); + ZSTDState *sp = ZSTDEncoderState(tif); ZSTD_inBuffer in_buffer; size_t zstd_ret; @@ -271,7 +273,7 @@ static int ZSTDEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s) static int ZSTDPostEncode(TIFF *tif) { static const char module[] = "ZSTDPostEncode"; - ZSTDState *sp = EncoderState(tif); + ZSTDState *sp = ZSTDEncoderState(tif); size_t zstd_ret; do @@ -297,7 +299,7 @@ static int ZSTDPostEncode(TIFF *tif) static void ZSTDCleanup(TIFF *tif) { - ZSTDState *sp = LState(tif); + ZSTDState *sp = GetZSTDState(tif); assert(sp != 0); @@ -325,7 +327,7 @@ static void ZSTDCleanup(TIFF *tif) static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap) { static const char module[] = "ZSTDVSetField"; - ZSTDState *sp = LState(tif); + ZSTDState *sp = GetZSTDState(tif); switch (tag) { @@ -347,7 +349,7 @@ static int ZSTDVSetField(TIFF *tif, uint32_t tag, va_list ap) static int ZSTDVGetField(TIFF *tif, uint32_t tag, va_list ap) { - ZSTDState *sp = LState(tif); + ZSTDState *sp = GetZSTDState(tif); switch (tag) { @@ -389,7 +391,7 @@ int TIFFInitZSTD(TIFF *tif, int scheme) tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(ZSTDState)); if (tif->tif_data == NULL) goto bad; - sp = LState(tif); + sp = GetZSTDState(tif); /* * Override parent get/set field methods. diff --git a/3rdparty/libtiff/tiffio.h b/3rdparty/libtiff/tiffio.h index 20460542f6..225f3c1bfe 100644 --- a/3rdparty/libtiff/tiffio.h +++ b/3rdparty/libtiff/tiffio.h @@ -77,10 +77,6 @@ typedef tstrile_t ttile_t; /* tile number */ typedef tmsize_t tsize_t; /* i/o size in bytes */ typedef void *tdata_t; /* image data ref */ -#if !defined(__WIN32__) && (defined(_WIN32) || defined(WIN32)) -#define __WIN32__ -#endif - /* * On windows you should define USE_WIN32_FILEIO if you are using tif_win32.c * or AVOID_WIN32_FILEIO if you are using something else (like tif_unix.c). @@ -88,7 +84,7 @@ typedef void *tdata_t; /* image data ref */ * By default tif_unix.c is assumed. */ -#if defined(_WINDOWS) || defined(__WIN32__) || defined(_Windows) +#if defined(_WIN32) #if !defined(__CYGWIN) && !defined(AVOID_WIN32_FILEIO) && \ !defined(USE_WIN32_FILEIO) #define AVOID_WIN32_FILEIO @@ -98,11 +94,11 @@ typedef void *tdata_t; /* image data ref */ #if defined(USE_WIN32_FILEIO) #define VC_EXTRALEAN #include -#ifdef __WIN32__ +#ifdef _WIN32 DECLARE_HANDLE(thandle_t); /* Win32 file handle */ #else typedef HFILE thandle_t; /* client data handle */ -#endif /* __WIN32__ */ +#endif /* _WIN32 */ #else typedef void *thandle_t; /* client data handle */ #endif /* USE_WIN32_FILEIO */ @@ -311,14 +307,15 @@ extern "C" /* * Auxiliary functions. */ - +#ifndef TIFF_DO_NOT_USE_NON_EXT_ALLOC_FUNCTIONS extern void *_TIFFmalloc(tmsize_t s); extern void *_TIFFcalloc(tmsize_t nmemb, tmsize_t siz); extern void *_TIFFrealloc(void *p, tmsize_t s); + extern void _TIFFfree(void *p); +#endif extern void _TIFFmemset(void *p, int v, tmsize_t c); extern void _TIFFmemcpy(void *d, const void *s, tmsize_t c); extern int _TIFFmemcmp(const void *p1, const void *p2, tmsize_t c); - extern void _TIFFfree(void *p); /* ** Stuff, related to tag handling and creating custom tags. @@ -508,6 +505,9 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *, TIFFOpenOptionsSetMaxSingleMemAlloc(TIFFOpenOptions *opts, tmsize_t max_single_mem_alloc); extern void + TIFFOpenOptionsSetMaxCumulatedMemAlloc(TIFFOpenOptions *opts, + tmsize_t max_cumulated_mem_alloc); + extern void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions *opts, TIFFErrorHandlerExtR handler, void *errorhandler_user_data); @@ -518,11 +518,11 @@ extern int TIFFReadRGBAImageOriented(TIFF *, uint32_t, uint32_t, uint32_t *, extern TIFF *TIFFOpen(const char *, const char *); extern TIFF *TIFFOpenExt(const char *, const char *, TIFFOpenOptions *opts); -#ifdef __WIN32__ +#ifdef _WIN32 extern TIFF *TIFFOpenW(const wchar_t *, const char *); extern TIFF *TIFFOpenWExt(const wchar_t *, const char *, TIFFOpenOptions *opts); -#endif /* __WIN32__ */ +#endif /* _WIN32 */ extern TIFF *TIFFFdOpen(int, const char *, const char *); extern TIFF *TIFFFdOpenExt(int, const char *, const char *, TIFFOpenOptions *opts); diff --git a/3rdparty/libtiff/tiffiop.h b/3rdparty/libtiff/tiffiop.h index fbf7b0700b..c4348206df 100644 --- a/3rdparty/libtiff/tiffiop.h +++ b/3rdparty/libtiff/tiffiop.h @@ -102,6 +102,13 @@ struct TIFFOffsetAndDirNumber }; typedef struct TIFFOffsetAndDirNumber TIFFOffsetAndDirNumber; +typedef union +{ + TIFFHeaderCommon common; + TIFFHeaderClassic classic; + TIFFHeaderBig big; +} TIFFHeaderUnion; + struct tiff { char *tif_name; /* name of open file */ @@ -153,20 +160,35 @@ struct tiff TIFFDirectory tif_dir; /* internal rep of current directory */ TIFFDirectory tif_customdir; /* custom IFDs are separated from the main ones */ - union - { - TIFFHeaderCommon common; - TIFFHeaderClassic classic; - TIFFHeaderBig big; - } tif_header; - uint16_t tif_header_size; /* file's header block and its length */ - uint32_t tif_row; /* current scanline */ - tdir_t tif_curdir; /* current directory (index) */ + TIFFHeaderUnion tif_header; /* file's header block Classic/BigTIFF union */ + uint16_t tif_header_size; /* file's header block and its length */ + uint32_t tif_row; /* current scanline */ + + /* There are IFDs in the file and an "active" IFD in memory, + * from which fields are "set" and "get". + * tif_curdir is set to: + * a) TIFF_NON_EXISTENT_DIR_NUMBER if there is no IFD in the file + * or the state is unknown, + * or the last read (i.e. TIFFFetchDirectory()) failed, + * or a custom directory was written. + * b) IFD index of last IFD written in the file. In this case the + * active IFD is a new (empty) one and tif_diroff is zero. + * If writing fails, tif_curdir is not changed. + * c) IFD index of IFD read from file into memory (=active IFD), + * even if IFD is corrupt and TIFFReadDirectory() returns 0. + * Then tif_diroff contains the offset of the IFD in the file. + * d) IFD index 0, whenever a custom directory or an unchained SubIFD + * was read. */ + tdir_t tif_curdir; /* current directory (index) */ + /* tif_curdircount: number of directories (main-IFDs) in file: + * - TIFF_NON_EXISTENT_DIR_NUMBER means 'dont know number of IFDs'. + * - 0 means 'empty file opened for writing, but no IFD written yet' */ + tdir_t tif_curdircount; uint32_t tif_curstrip; /* current strip for read/write */ uint64_t tif_curoff; /* current offset for read/write */ uint64_t tif_lastvalidoff; /* last valid offset allowed for rewrite in place. Used only by TIFFAppendToStrip() */ - uint64_t tif_dataoff; /* current offset for writing dir */ + uint64_t tif_dataoff; /* current offset for writing dir (IFD) */ /* SubIFD support */ uint16_t tif_nsubifd; /* remaining subifds to write */ uint64_t tif_subifdoff; /* offset for patching SubIFD link */ @@ -233,7 +255,9 @@ struct tiff void *tif_errorhandler_user_data; TIFFErrorHandlerExtR tif_warnhandler; void *tif_warnhandler_user_data; - tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */ + tmsize_t tif_max_single_mem_alloc; /* in bytes. 0 for unlimited */ + tmsize_t tif_max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */ + tmsize_t tif_cur_cumulated_mem_alloc; /* in bytes */ }; struct TIFFOpenOptions @@ -243,6 +267,7 @@ struct TIFFOpenOptions TIFFErrorHandlerExtR warnhandler; /* may be NULL */ void *warnhandler_user_data; /* may be NULL */ tmsize_t max_single_mem_alloc; /* in bytes. 0 for unlimited */ + tmsize_t max_cumulated_mem_alloc; /* in bytes. 0 for unlimited */ }; #define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */ @@ -331,7 +356,7 @@ struct TIFFOpenOptions #define ftell(stream, offset, whence) ftello(stream, offset, whence) #endif #endif -#if defined(__WIN32__) && !(defined(_MSC_VER) && _MSC_VER < 1400) && \ +#if defined(_WIN32) && \ !(defined(__MSVCRT_VERSION__) && __MSVCRT_VERSION__ < 0x800) typedef unsigned int TIFFIOSize_t; #define _TIFF_lseek_f(fildes, offset, whence) \ @@ -437,9 +462,6 @@ extern "C" extern void *_TIFFCheckRealloc(TIFF *, void *, tmsize_t, tmsize_t, const char *); - extern double _TIFFUInt64ToDouble(uint64_t); - extern float _TIFFUInt64ToFloat(uint64_t); - extern float _TIFFClampDoubleToFloat(double); extern uint32_t _TIFFClampDoubleToUInt32(double);