From 6d4cf4b392c53e3edb8573d89b5ca4b6257bb99f Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 5 Nov 2019 09:58:05 +0100 Subject: Update bundled libtiff to version 4.1.0 [ChangeLog][Third-Party Code] Bundled libtiff was updated to version 4.1.0 Change-Id: I3e841863c5cf8588bf62b6520f34e64909394998 (cherry picked from commit ba1fb21bc61a2075c7fd058e7f7ba5caf7d2f400) Reviewed-by: Liang Qi --- src/3rdparty/libtiff/ChangeLog | 884 ++++++++++++++++++ src/3rdparty/libtiff/RELEASE-DATE | 2 +- src/3rdparty/libtiff/VERSION | 2 +- src/3rdparty/libtiff/libtiff/libtiff.def | 7 + src/3rdparty/libtiff/libtiff/mkg3states.c | 2 +- src/3rdparty/libtiff/libtiff/tif_aux.c | 26 +- src/3rdparty/libtiff/libtiff/tif_config.h | 2 +- src/3rdparty/libtiff/libtiff/tif_config.h.in | 2 +- src/3rdparty/libtiff/libtiff/tif_dir.c | 67 +- src/3rdparty/libtiff/libtiff/tif_dir.h | 12 +- src/3rdparty/libtiff/libtiff/tif_dirread.c | 1239 ++++++++++++++++++-------- src/3rdparty/libtiff/libtiff/tif_dirwrite.c | 343 +++++-- src/3rdparty/libtiff/libtiff/tif_flush.c | 118 ++- src/3rdparty/libtiff/libtiff/tif_getimage.c | 2 +- src/3rdparty/libtiff/libtiff/tif_jpeg.c | 17 +- src/3rdparty/libtiff/libtiff/tif_luv.c | 17 +- src/3rdparty/libtiff/libtiff/tif_lzw.c | 2 + src/3rdparty/libtiff/libtiff/tif_ojpeg.c | 91 +- src/3rdparty/libtiff/libtiff/tif_open.c | 18 + src/3rdparty/libtiff/libtiff/tif_pixarlog.c | 9 +- src/3rdparty/libtiff/libtiff/tif_print.c | 10 +- src/3rdparty/libtiff/libtiff/tif_read.c | 226 +++-- src/3rdparty/libtiff/libtiff/tif_strip.c | 3 +- src/3rdparty/libtiff/libtiff/tif_thunder.c | 10 +- src/3rdparty/libtiff/libtiff/tif_write.c | 138 +-- src/3rdparty/libtiff/libtiff/tif_zip.c | 58 +- src/3rdparty/libtiff/libtiff/tiffio.h | 10 + src/3rdparty/libtiff/libtiff/tiffiop.h | 15 + src/3rdparty/libtiff/libtiff/tiffvers.h | 4 +- src/3rdparty/libtiff/port/snprintf.c | 4 + src/3rdparty/libtiff/qt_attribution.json | 2 +- 31 files changed, 2630 insertions(+), 712 deletions(-) diff --git a/src/3rdparty/libtiff/ChangeLog b/src/3rdparty/libtiff/ChangeLog index 1f50e20..01e2182 100644 --- a/src/3rdparty/libtiff/ChangeLog +++ b/src/3rdparty/libtiff/ChangeLog @@ -1,3 +1,887 @@ +2019-11-03 Bob Friesenhahn + + libtiff 4.1.0 released. + + Added a step for updating the legacy ChangeLog file. + + Ignore emacs temporary files (ending with tilde character). + + Added release summary page for the 4.1.0 release. + + Fix Cmake HAVE_GETOPT for systems which declare getopt in stdio.h. Fix utility baked-in getopt prototype which appears when HAVE_GETOPT is not defined. + + Fax2tiff.sh needs to remove its output file in advance. Syntax changes so that bash is not required. + +2019-10-26 Even Rouault + + tif_jpeg.c: extra cast to silence Coverity warning. GDAL CID 1406475. + +2019-10-23 Even Rouault + + tif_jpeg.c: fix warning added by previous commit (on 32bit builds) + +2019-10-23 Even Rouault + + Merge branch 'coverity-fixes' into 'master' + Coverity fixes + + See merge request libtiff/libtiff!94 + +2019-10-22 Timothy Lyanguzov + + Use 64-bit calculations correctly. + + Fix size calculation to use 64-bit tmsize_t correctly. + + Make bytesperclumpline calculations using tmsize_t type. + +2019-10-03 Even Rouault + + tif_read: align code of TIFFReadRawStrip() and TIFFReadRawTile() that differed for non good reason. Non-functional change normally. (fixes GitLab #162) + +2019-10-01 Even Rouault + + HTML: update for GitLab issues. + +2019-09-29 Even Rouault + + html/v3.5.6-beta.html: redact URL of defunct web site. + + Website: update links to mailing list. + +2019-09-17 Even Rouault + + TIFFReadAndRealloc(): avoid too large memory allocation attempts. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17244 + +2019-09-03 Even Rouault + + ByteCountLooksBad and EstimateStripByteCounts: avoid unsigned integer overflows. Fixes https://oss-fuzz.com/testcase-detail/5686156066291712 and https://oss-fuzz.com/testcase-detail/6332499206078464 + +2019-09-02 Even Rouault + + tif_ojpeg.c: avoid relying on isTiled macro being wrapped in () + + tif_ojpeg.c: avoid use of uninitialized memory on edge/broken file. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 + + tiff_read_rgba_fuzzer.cc: add a -DSTANDALONE mode for easier reproduction of oss-fuzz reports + +2019-09-01 Even Rouault + + tif_dirread.c: allocChoppedUpStripArrays(). avoid unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16846 + +2019-08-27 Even Rouault + + tif_ojpeg.c: avoid unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16793 + +2019-08-26 Even Rouault + + TIFFReadDirEntryData(): rewrite to avoid unsigned integer overflow (not a bug). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16792 + + TIFFFetchDirectory(): fix invalid cast from uint64 to tmsize_t. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16784 + +2019-08-25 Even Rouault + + JPEG: avoid use of unintialized memory on corrupted files. + Follow-up of cf3ce6fab894414a336546f62adc57f02590a22c + Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16602 + Credit to OSS Fuzz + +2019-08-23 Even Rouault + + _TIFFPartialReadStripArray(): avoid unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16685 + + OJPEGWriteHeaderInfo(): avoid unsigned integer overflow on strile dimensions close to UINT32_MAX. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16683 + + TIFFFillStrip(): avoid harmless unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16653 + + EstimateStripByteCounts(): avoid unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16643& + + tif_ojpeg: avoid unsigned integer overflow (probably not a bug). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16635 + + tif_thunder: avoid unsigned integer overflow (not a bug). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16632 + +2019-08-22 Even Rouault + + _TIFFMultiply32() / _TIFFMultiply64(): avoid relying on unsigned integer overflow (not a bug) + + EstimateStripByteCounts(): avoid unsigned integer overflow. + +2019-08-21 Even Rouault + + EstimateStripByteCounts(): avoid unsigned integer overflow. + +2019-08-20 Even Rouault + + EstimateStripByteCounts(): avoid harmless unsigned integer overflow. + + _TIFFPartialReadStripArray(): avoid triggering unsigned integer overflow with -fsanitize=unsigned-integer-overflow (not a bug, this is well defined by itself) + +2019-08-18 Even Rouault + + tiff2ps: fix use of wrong data type that caused issues (/Height being written as 0) on 64-bit big endian platforms + +2019-08-16 Even Rouault + + setByteArray(): fix previous commit. + + setByteArray(): avoid potential signed integer overflow. Pointed by Hendra Gunadi. No actual problem known (which does not mean there wouldn't be any. Particularly on 32bit builds) + +2019-08-15 Even Rouault + + RGBA interface: fix integer overflow potentially causing write heap buffer overflow, especially on 32 bit builds. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16443. Credit to OSS Fuzz + +2019-08-14 Even Rouault + + Merge branch 'fix_integer_overflow' into 'master' + Fix integer overflow in _TIFFCheckMalloc() and other implementation-defined behaviour (CVE-2019-14973) + + See merge request libtiff/libtiff!90 + +2019-08-13 Even Rouault + + Fix integer overflow in _TIFFCheckMalloc() and other implementation-defined behaviour (CVE-2019-14973) + _TIFFCheckMalloc()/_TIFFCheckRealloc() used a unsafe way to detect overflow + in the multiplication of nmemb and elem_size (which are of type tmsize_t, thus + signed), which was especially easily triggered on 32-bit builds (with recent + enough compilers that assume that signed multiplication cannot overflow, since + this is undefined behaviour by the C standard). The original issue which lead to + this fix was trigged from tif_fax3.c + + There were also unsafe (implementation defied), and broken in practice on 64bit + builds, ways of checking that a uint64 fits of a (signed) tmsize_t by doing + (uint64)(tmsize_t)uint64_var != uint64_var comparisons. Those have no known + at that time exploits, but are better to fix in a more bullet-proof way. + Or similarly use of (int64)uint64_var <= 0. + +2019-08-12 Even Rouault + + TIFFClientOpen(): fix memory leak if one of the required callbacks is not provided. Fixed Coverity GDAL CID 1404110 + + OJPEGReadBufferFill(): avoid very long processing time on corrupted files. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16400. master only + +2019-08-10 Even Rouault + + oss-fuzz/tiff_read_rgba_fuzzer.cc: fix wrong env variable value in previous commit + + oss-fuzz/tiff_read_rgba_fuzzer.cc: avoid issue with libjpeg-turbo and MSAN + + OJPEG: fix integer division by zero on corrupted subsampling factors. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=15824. Credit to OSS Fuzz + + Merge branch 'ossfuzz_i386' + + contrib/oss-fuzz/build.sh: fix for i386 build of jbigkit, and use $LIB_FUZZING_ENGINE + +2019-08-10 Even Rouault + + Merge branch 'patch-1' into 'master' + fix two tiny typos + + See merge request libtiff/libtiff!89 + +2019-08-10 Reto Kromer + + fix two tiny typos. + +2019-08-09 Even Rouault + + Merge branch 'patch-1' into 'master' + fix a typo in man page + + See merge request libtiff/libtiff!88 + +2019-08-09 Reto Kromer + + fix typo. + +2019-08-04 Even Rouault + + Merge branch 'TIFFTAGID_Zero_reading_IGNORE' into 'master' + Suppressed Reading of Tiff tags with ID = 0 (like GPSVERSIONID) corrected. + + See merge request libtiff/libtiff!77 + +2019-08-04 Su Laus + + Reading of Tiff tags with ID = 0 (like GPSVERSIONID) corrected. + IGNORE placeholder in tif_dirread.c is now replaced by a field dir_ignore in the TIFFDirEntry structure + + Currently, in tif_dirread.c a special IGNORE value for the tif tags is defined + in order to flag status preventing already processed tags from further processing. + This irrational behaviour prevents reading of custom tags with id code 0 - like tag GPSVERSIONID from EXIF 2.31 definition. + + An additional field 'tdir_ignore' is now added to the TIFFDirEntry structure and code is changed + to allow tags with id code 0 to be read correctly. + + This change was already proposed as pending improvement in tif_dirread.c around line 32. + + Reference is also made to: + - Discussion in https://gitlab.com/libtiff/libtiff/merge_requests/39 + - http://bugzilla.maptools.org/show_bug.cgi?id=2540 + + Comments and indention adapted. + + Preparation to rebase onto master + +2019-07-16 Even Rouault + + Merge branch 'cmake_amd64' into 'master' + CMakeLists.txt: properly set value of HOST_FILLORDER to LSB2MSB for Windows CMake builds + + See merge request libtiff/libtiff!87 + +2019-07-15 Even Rouault + + CMakeLists.txt: properly set value of HOST_FILLORDER to LSB2MSB for Windows CMake builds + As can be seen in https://ci.appveyor.com/project/rleigh-codelibre/libtiff-didfs/builds/25846668/job/ory5w098j8wcij9x + log, the HOST_FILLORDER is not properly set: + + [00:02:58] -- CMAKE_HOST_SYSTEM_PROCESSOR set to AMD64 + [00:02:58] -- HOST_FILLORDER set to FILLORDER_MSB2LSB + + Ther reason is that we match the "amd64.*" lowercase string whereas + CMAKE_HOST_SYSTEM_PROCESSOR is set to AMD64 uppercase. + +2019-07-09 Even Rouault + + TIFFWriteCheck(): call TIFFForceStrileArrayWriting() when needed (should have gone with eaeca6274ae71cdfaeb9f673b6fb0f3cfc0e6ce5) (master only) + +2019-07-09 Even Rouault + + Merge branch 'fix_chromium_925269' into 'master' + OJPEG: avoid use of unintialized memory on corrupted files + + See merge request libtiff/libtiff!86 + +2019-07-05 Even Rouault + + OJPEG: avoid use of unintialized memory on corrupted files. + Fixes https://bugs.chromium.org/p/chromium/issues/detail?id=925269 + Patch from Lei Zhang with little adaptations. + +2019-06-29 Even Rouault + + Merge branch 'fix-division-by-zero' into 'master' + Return infinite distance when denominator is zero. + + See merge request libtiff/libtiff!85 + +2019-06-29 Dirk Lemstra + + Return infinite distance when denominator is zero. + +2019-06-29 Even Rouault + + Merge branch 'typetests' into 'master' + Add test to check that libtiff types have the correct size + + See merge request libtiff/libtiff!57 + +2019-05-31 Thomas Bernard + + make TIFF_SSIZE_T the same bitwidth as TIFF_SIZE_T. + it was previously the same bitwidth as unsigned char * + Pointers can be larger than size_t. + +2019-05-31 Thomas Bernard + + Add test to check that libtiff types have the correct size. + in configure/CMakeList.txt : + + - TIFF_INT8_T/TIFF_UINT8_T is signed/unsigned char + sizeof(char)==1 in C standard + - TIFF_INT16_T/TIFF_UINT16_T is signed/unsigned short + sizeof(short)>=2 in C standard + - TIFF_INT32_T/TIFF_UINT32_T is defined so its sizeof() is 4 + + - TIFF_INT64_T/TIFF_UINT64_T is defined so its sizeof() is 8 + + - TIFF_SIZE_T is defined so it has same sizeof() than size_t + + - TIFF_SSIZE_T is defined so it has same sizeof() than unsigned char * + +2019-05-29 Even Rouault + + Merge branch 'defer_strile_writing' into 'master' + Add TIFFDeferStrileArrayWriting() and TIFFForceStrileArrayWriting() + + See merge request libtiff/libtiff!82 + +2019-05-29 Even Rouault + + Merge branch 'TIFFReadFromUserBuffer' into 'master' + Add TIFFReadFromUserBuffer() + + See merge request libtiff/libtiff!81 + +2019-05-26 Even Rouault + + Fix vulnerability in 'D' (DeferStrileLoad) mode (master only) (fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14908) + +2019-05-25 Even Rouault + + Replace 'stripped' by 'striped' in error messages. + +2019-05-25 Even Rouault + + Add TIFFDeferStrileArrayWriting() and TIFFForceStrileArrayWriting() + Those advanced writing functions must be used in a particular sequence + to make their intended effect. Their aim is to control when/where + the [Strip/Tile][Offsets/ByteCounts] arrays are written into the file. + + The purpose of this is to generate 'cloud-optimized geotiff' files where + the first KB of the file only contain the IFD entries without the potentially + large strile arrays. Those are written afterwards. + + The typical sequence of calls is: + TIFFOpen() + [ TIFFCreateDirectory(tif) ] + Set fields with calls to TIFFSetField(tif, ...) + TIFFDeferStrileArrayWriting(tif) + TIFFWriteCheck(tif, ...) + TIFFWriteDirectory(tif) + ... potentially create other directories and come back to the above directory + TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file + + See test/defer_strile_writing.c for a practical example. + +2019-05-24 Even Rouault + + Fix vulnerability introduced by defer strile loading (master only) + Found on GDAL with https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14894 + Disabling the TIFF_DEFERSTRILELOAD bit in ChopupStripArray() was a + bad idea since when using TIFFReadDirectory() to reload the directory again + would lead to a different value of td_rowsperstrip, which could confuse + readers if they relied on the value found initially. + + Fix typo in error message (master only) + +2019-05-22 Even Rouault + + Add TIFFReadFromUserBuffer() + This function replaces the use of TIFFReadEncodedStrip()/TIFFReadEncodedTile() + when the user can provide the buffer for the input data, for example when + he wants to avoid libtiff to read the strile offset/count values from the + [Strip|Tile][Offsets/ByteCounts] array. + + libtiff.def: add missing new symbols. + + test/defer_strile_loading.c: fix warning with Visual C++ + + _TIFFRewriteField(): fix for bigtiff case (master only) + 116cf67f4c59196605abdb244657c3070c4310af made StripByteCount/TileByteCount to + always be rewritten as TIFF_LONG8. + +2019-05-21 Even Rouault + + Merge branch 'ondemand_strile_offbytecount_loading' into 'master' + Make defer strile offset/bytecount loading available at runtime + + See merge request libtiff/libtiff!79 + +2019-05-21 Even Rouault + + Merge branch 'bigtiff_write_bytecount_on_long_when_possible' into 'master' + Create TileByteCounts/StripByteCounts tag with SHORT (ClassicTIFF/BigTIFF) or LONG (BigTIFF) type when possible + + See merge request libtiff/libtiff!78 + +2019-05-21 Even Rouault + + Merge branch 'html_link' into 'master' + libtiff.html, bigtiffpr.html: absolute => relative link + + See merge request libtiff/libtiff!80 + +2019-05-14 Thomas Bernard + + libtiff.html, bigtiffpr.html: absolute => relative link. + +2019-05-10 Even Rouault + + Make defer strile offset/bytecount loading available at runtime. + ... and add per-strile offset/bytecount loading capabilities. + + Part of this commit makes the behaviour that was previously met when + libtiff was compiled with -DDEFER_STRILE_LOAD available for default builds + when specifying the new 'D' (Deferred) TIFFOpen() flag. In that mode, the [Tile/Strip][ByteCounts/Offsets] + arrays are only loaded when first accessed. This can speed-up the opening + of files stored on the network when just metadata retrieval is needed. + This mode has been used for years by the GDAL library when compiled with + its embeded libtiff copy. + + To avoid potential out-of-tree code (typically codecs) that would use + the td_stripbytecount and td_stripoffset array inconditionnaly assuming they + have been loaded, those have been suffixed with _p (for protected). The + use of the new functions mentionned below is then recommended. + + Another addition of this commit is the capability of loading only the + values of the offset/bytecount of the strile of interest instead of the + whole array. This is enabled with the new 'O' (Ondemand) flag of TIFFOpen() + (which implies 'D'). That behaviour has also been used by GDAL, which hacked + into the td_stripoffset/td_stripbytecount arrays directly. The new code + added in the _TIFFFetchStrileValue() and _TIFFPartialReadStripArray() internal + functions is mostly a port of what was in GDAL GTiff driver previously. + + Related to that, the public TIFFGetStrileOffset[WithErr]() and TIFFGetStrileByteCount[WithErr]() + functions have been added to API. They are of particular interest when + using sparse files (with offset == bytecount == 0) and you want to detect + if a strile is present or not without decompressing the data, or updating + an existing sparse file. + They will also be used to enable a future enhancement where client code can entirely + skip bytecount loading in some situtations + + A new test/defer_strile_loading.c test has been added to test the above + capabilities. + +2019-05-10 Even Rouault + + Creation: use SHORT type when possible for StripByteCounts/TileByteCounts + This follows the same logic as previous commit. + +2019-05-09 Even Rouault + + BigTIFF creation: write TileByteCounts/StripByteCounts tag with LONG when possible + In most situations of BigTIFF file, the tile/strip sizes are of reasonable size, + that is they fit on a 4-byte LONG. So in that case, use LONG instead of LONG8 + to save some space. For uncompressed file, it is easy to detect such situations + by checking at the TIFFTileSize64()/TIFFStripSize64() return. For compressed file, + we must take into account the fact that compression may sometimes result in + larger compressed data. So we allow this optimization only for a few select + compression times, and take a huge security margin (10x factor). We also only + apply this optimization on multi-strip files, so as to allow easy on-the-fly + growing of single-strip files whose strip size could grow above the 4GB threshold. + + This change is compatible with the BigTIFF specification. According to + https://www.awaresystems.be/imaging/tiff/bigtiff.html: + "The StripOffsets, StripByteCounts, TileOffsets, and TileByteCounts tags are + allowed to have the datatype TIFF_LONG8 in BigTIFF. Old datatypes TIFF_LONG, + and TIFF_SHORT where allowed in the TIFF 6.0 specification, are still valid in BigTIFF, too. " + On a practical point of view, this is also compatible on reading/writing of + older libtiff 4.X versions. + + The only glitch I found, which is rather minor, is when using such a BigTIFF + file with TileByteCounts/StripByteCounts written with TIFF_LONG, and updating + it with an older libtiff 4.X version with a change in the + [Tile/Strip][ByteCounts/Offsets] array. In that case the _TIFFRewriteField() + function will rewrite the directory and array with TIFF_LONG8, instead of updating + the existing array (this is an issue fixed by this commit). The file will + still be valid however, hence the minor severity of this. + +2019-05-08 Even Rouault + + Merge branch 'bug2799' into 'master' + fix fax2tiff + + See merge request libtiff/libtiff!55 + +2019-05-08 Even Rouault + + Merge branch 'bug_2829' into 'master' + WIN32: use tif_win32.c when building with CMake + + See merge request libtiff/libtiff!75 + +2019-05-06 Even Rouault + + Merge branch 'FILESOURCE_SCENETYPE_reading' into 'master' + Reading error for FileSource and SceneType tags corrected. + + See merge request libtiff/libtiff!76 + +2019-05-06 Su Laus + + Reading error for FileSource and SceneType tags corrected. + EXIF tags FILESOURCE and SCENETYPE are defined as TIFF_UNDEFINED and field_readcount==1! + There is a bug in TIFFReadDirEntryByte() preventing to read correctly type TIFF_UNDEFINED fields with field_readcount==1 + Upgrade of TIFFReadDirEntryByte() with added TIFF_UNDEFINED switch-entry allows libtiff to read those tags correctly. + +2019-04-25 Thomas Bernard + + WIN32: use tif_win32.c when building with CMake. + see http://bugzilla.maptools.org/show_bug.cgi?id=2829 + + the top CMakeLists.txt defines + win32_io and USE_WIN32_FILEIO + + WIN32_IO is defined nowhere in CMake (only in automake things) + +2019-04-25 Even Rouault + + Merge branch 'gitlab_pages' into 'master' + Advertise https://libtiff.gitlab.io/libtiff/ as mirror + + See merge request libtiff/libtiff!70 + +2019-04-25 Even Rouault + + Merge branch 'bug_2844' into 'master' + tiff2ps.c: PSDataColorContig(): avoid heap buffer overrun + + See merge request libtiff/libtiff!69 + +2019-04-25 Even Rouault + + Merge branch 'issue_2785' into 'master' + tiff2pdf.c: don't call t2p_tile_collapse_left() for Ycbcr + + See merge request libtiff/libtiff!64 + +2019-04-11 Even Rouault + + Merge branch 'fix_gdal_1439' into 'master' + TIFFWriteEncodedStrip/TIFFWriteEncodedTile: fix rewriting of LZW-compressed data + + See merge request libtiff/libtiff!74 + +2019-04-11 Even Rouault + + TIFFWriteEncodedStrip/TIFFWriteEncodedTile: fix rewriting of LZW-compressed data + Fixes https://github.com/OSGeo/gdal/issues/1439 + + When rewriting a LZW tile/strip whose existing size is very close to a multiple of + 1024 bytes (and larger than 8192 bytes) with compressed data that is larger, + the new data was not placed at the end of the file, causing corruption. + +2019-04-08 Even Rouault + + Merge branch 'bug2848' into 'master' + tif_luv.c: LogLuvSetupEncode() error must return 0 + + See merge request libtiff/libtiff!72 + +2019-04-03 Thomas Bernard + + build/gitlab-ci: fix typo. + + show test-suite.log in gitlab-ci. + useful when build fails + + Add output check for tiff2ps. + note : the reference files have been generated in master branch + +2019-03-23 Even Rouault + + tif_read.c: potentially fix false positive from Coverity Scan. CID 1400288 + + tif_read.c: potentially fix false positive from Coverity Scan. CID 1400271 + + tif_zip.c: remove dead code. CID 1400360. + + tif_webp.c: remove false positive warning about dereference before null check. CID 1400255 + + tif_pixarlog.c: remove dead code. CID 1400342. + + tif_pixarlog.c: avoid false positive Coverity Scan warnings about overflow. CID 1400300 and 1400367 + + tif_lzw.c: silence CoverityScan false positive. CID 1400355. + + tif_luv.c: silence CoverityScan false positive. CID 1400231, 1400251, 1400254, 1400272, 1400318, 1400356 + + TryChopUpUncompressedBigTiff(): avoid potential division by zero. master only. GDAL Coverity CID 1400263 + +2019-03-22 Thomas Bernard + + tif_luv.c: LogLuvSetupEncode() error must return 0. + see http://bugzilla.maptools.org/show_bug.cgi?id=2848 + + if wrongly returning 1, the processing of incorrect file continues, + which causes problems. + +2019-03-22 Thomas Bernard + + add a test for fax2tiff tool. + +2019-02-28 Thomas Bernard + + tiff2pdf.c: don't call t2p_tile_collapse_left() when buffer size is wrong + see http://bugzilla.maptools.org/show_bug.cgi?id=2785 + + Advertise https://libtiff.gitlab.io/libtiff/ as mirror. + I'm put it above the maptools.org mirror because + Even Rouault believe at some point it will be completely removed + +2019-02-28 Even Rouault + + Merge branch 'bug_2826' into 'master' + tiff2pdf.c: check colormap pointers when loading CMYK with colormap + + See merge request libtiff/libtiff!65 + +2019-02-28 Thomas Bernard + + tiff2pdf.c: check colormap pointers. + Avoid access to non initialized pointers + http://bugzilla.maptools.org/show_bug.cgi?id=2826 + +2019-02-27 Even Rouault + + Merge branch 'fix_warnings' into 'master' + tiff2ps.c: fix warning caused by integer promotion + + See merge request libtiff/libtiff!68 + +2019-02-23 Thomas Bernard + + PSDataColorContig(): avoid heap buffer overrun. + fixes http://bugzilla.maptools.org/show_bug.cgi?id=2844 + each iteration of the loop read nc bytes + +2019-02-22 Thomas Bernard + + tiff2ps.c: fix warning caused by integer promotion. + uint8 value is promoted to int in (value << 24) so -fsanitize + yield runtime errors : + tiff2ps.c:2969:33: runtime error: left shift of 246 by 24 places cannot be represented in type 'int' + +2019-02-22 Even Rouault + + Merge branch 'large_strile_improvements' into 'master' + Large strile support improvements + + See merge request libtiff/libtiff!63 + +2019-02-21 Even Rouault + + Merge branch 'gitlab-pages' into 'master' + ci: Add pages job + + See merge request libtiff/libtiff!45 + +2019-02-19 Even Rouault + + Merge branch 'issue_2833' into 'master' + tiffcp.c: check that (Tile Width)*(Samples/Pixel) do no overflow + + See merge request libtiff/libtiff!60 + +2019-02-19 Even Rouault + + Merge branch 'issue_2831' into 'master' + tiffcrop.c: fix invertImage() for bps 2 and 4 + + See merge request libtiff/libtiff!61 + +2019-02-19 Even Rouault + + Merge branch 'issue_2842' into 'master' + move _TIFFClampDoubleToFloat() to tif_aux.c + + See merge request libtiff/libtiff!62 + +2019-02-19 Even Rouault + + tif_zip.c: allow reading and writing strips/tiles with more than 4 GB of compressed or uncompressed data + + tif_dirread.c: when strip chopping is enabled, extend this mechanism to multi-strip uncompressed files with strips larger than 2GB to expose them as strips of ~500 MB + +2019-02-19 Even Rouault + + Merge branch 'size_t_typo' into 'master' + CMakeLists.txt: fix TIFF_SIZE_T + + See merge request libtiff/libtiff!59 + +2019-02-12 Thomas Bernard + + move _TIFFClampDoubleToFloat() to tif_aux.c. + the same function was declared in tif_dir.c and tif_dirwrite.c + + see http://bugzilla.maptools.org/show_bug.cgi?id=2842 + +2019-02-11 Thomas Bernard + + tiffcrop.c: fix invertImage() for bps 2 and 4. + too much bytes were processed, causing a heap buffer overrun + http://bugzilla.maptools.org/show_bug.cgi?id=2831 + the loop counter must be + for (col = 0; col < width; col += 8 / bps) + + Also the values were not properly calculated. It should be + 255-x, 15-x, 3-x for bps 8, 4, 2. + + But anyway it is easyer to invert all bits as 255-x = ~x, etc. + (substracting from a binary number composed of all 1 is like inverting + the bits) + +2019-02-11 Thomas Bernard + + tiffcp.c: use INT_MAX. + + check that (Tile Width)*(Samples/Pixel) do no overflow. + fixes bug 2833 + +2019-02-03 Thomas Bernard + + CMakeLists.txt: fix TIFF_SIZE_T. + +2019-02-02 Even Rouault + + Merge branch 'master' into 'master' + Fix for simple memory leak that was assigned CVE-2019-6128. + + See merge request libtiff/libtiff!50 + +2019-02-02 Even Rouault + + Merge branch 'bug2835' into 'master' + tiff2ps: fix heap-buffer-overflow + + See merge request libtiff/libtiff!53 + +2019-02-02 Even Rouault + + Fix warning (use of uninitialized value) added per d0a842c5dbad2609aed43c701a12ed12461d3405 (fixes https://gitlab.com/libtiff/libtiff/merge_requests/54#note_137742985) + +2019-02-02 Yuri Aksenov + + fix fax2tiff. + see http://bugzilla.maptools.org/show_bug.cgi?id=2799 + fixes d9bc8472e72549f29c0062c1cbd3d56f279f3be2 + +2019-02-02 Even Rouault + + Merge branch 'tiffcrop' into 'master' + tiffcrop: shut up clang warnings + + See merge request libtiff/libtiff!52 + +2019-02-01 Even Rouault + + Merge branch 'bug2833' into 'master' + TIFFWriteDirectoryTagTransferfunction() : fix NULL dereferencing + + See merge request libtiff/libtiff!54 + +2019-02-01 Even Rouault + + Merge branch 'gitignore' into 'master' + add test/ files to .gitignore + + See merge request libtiff/libtiff!56 + +2019-02-01 Even Rouault + + Merge branch 'master' into 'master' + tif_dir: unset transferfunction field if necessary (CVE-2018-19210) + + See merge request libtiff/libtiff!47 + +2019-01-29 Thomas Bernard + + add test/ files to .gitignore. + +2019-01-29 Thomas Bernard + + TIFFWriteDirectoryTagTransferfunction() : fix NULL dereferencing. + http://bugzilla.maptools.org/show_bug.cgi?id=2833 + + we must check the pointer is not NULL before memcmp() the memory + +2019-01-29 Thomas Bernard + + tiff2ps: fix heap-buffer-overflow. + http://bugzilla.maptools.org/show_bug.cgi?id=2834 + + usually the test (i < byte_count) is OK because the byte_count is divisible by samplesperpixel. + But if that is not the case, (i + ncomps) < byte_count should be used, or + maybe (i + samplesperpixel) <= byte_count + +2019-01-28 Thomas Bernard + + tiffcrop: shut up clang warnings. + make the out filename building a bit more simple + and remove the use of strcat() + +2019-01-23 Scott Gayou + + Fix for simple memory leak that was assigned CVE-2019-6128. + pal2rgb failed to free memory on a few errors. This was reported + here: http://bugzilla.maptools.org/show_bug.cgi?id=2836. + +2019-01-05 Bob Friesenhahn + + Fix tiff2ps error regarding "Inconsistent value of es" by allowing es to be zero. Problem was reported to the tiff mailing list by Julian H. Stacey on January 5, 2019. + +2018-12-13 Hugo Lefeuvre + + tif_dir: unset transferfunction field if necessary. + The number of entries in the transfer table is determined as following: + + (td->td_samplesperpixel - td->td_extrasamples) > 1 ? 3 : 1 + + This means that whenever td->td_samplesperpixel or td->td_extrasamples are + modified we also need to make sure that the number of required entries in + the transfer table didn't change. + + If it changed and the number of entries is higher than before we should + invalidate the transfer table field and free previously allocated values. + In the other case there's nothing to do, additional tf entries won't harm + and properly written code will just ignore them since spp - es < 1. + + For instance this situation might happen when reading an OJPEG compressed + image with missing SamplesPerPixel tag. In this case the SamplesPerPixel + field might be updated after setting the transfer table. + + see http://bugzilla.maptools.org/show_bug.cgi?id=2500 + + This commit addresses CVE-2018-19210. + +2018-12-08 Bob Friesenhahn + + Do not attempt to re-sync zip stream after reported data error from inflate(). + +2018-12-07 Even Rouault + + Merge branch 'resource-leaks' into 'master' + Fix two resource leaks + + See merge request libtiff/libtiff!43 + +2018-12-07 Even Rouault + + Merge branch 'build-jbig' into 'master' + add jbig support to the fuzzer + + See merge request libtiff/libtiff!42 + +2018-12-01 Bob Friesenhahn + + tiffcrop.c: Avoid new clang warning about tools/tiffcrop.c "size argument in 'strncat' call appears to be size of the source". + +2018-11-28 Even Rouault + + Merge branch 'webp_memleak' into 'master' + fixed mem leak in webp compression + + See merge request libtiff/libtiff!48 + +2018-11-28 Norman Barker + + fixed mem leak in webp compression. + +2018-11-20 Even Rouault + + Merge branch 'lossless_webp' into 'master' + fixed lossless webp compression config + + See merge request libtiff/libtiff!46 + +2018-11-20 Norman Barker + + fixed lossless webp compression config. + +2018-11-18 Bob Friesenhahn + + snprintf porting fix for Visual Studio 2003. + +2018-11-18 Roger Leigh + + ci: Add pages job. + +2018-11-10 Bob Friesenhahn + + Change references from defunct ftp site to https site. + 2018-11-10 Bob Friesenhahn * configure.ac: libtiff 4.0.10 released. diff --git a/src/3rdparty/libtiff/RELEASE-DATE b/src/3rdparty/libtiff/RELEASE-DATE index 94d1f0c..ad4fa62 100644 --- a/src/3rdparty/libtiff/RELEASE-DATE +++ b/src/3rdparty/libtiff/RELEASE-DATE @@ -1 +1 @@ -20181110 +20191103 diff --git a/src/3rdparty/libtiff/VERSION b/src/3rdparty/libtiff/VERSION index 2d2d681..ee74734 100644 --- a/src/3rdparty/libtiff/VERSION +++ b/src/3rdparty/libtiff/VERSION @@ -1 +1 @@ -4.0.10 +4.1.0 diff --git a/src/3rdparty/libtiff/libtiff/libtiff.def b/src/3rdparty/libtiff/libtiff/libtiff.def index 341c719..e34fac5 100644 --- a/src/3rdparty/libtiff/libtiff/libtiff.def +++ b/src/3rdparty/libtiff/libtiff/libtiff.def @@ -20,6 +20,7 @@ EXPORTS TIFFAccessTagMethods TIFFDataWidth TIFFDefaultStripSize TIFFDefaultTileSize + TIFFDeferStrileArrayWriting TIFFError TIFFErrorExt TIFFFdOpen @@ -37,6 +38,7 @@ EXPORTS TIFFAccessTagMethods TIFFFindField TIFFFlush TIFFFlushData + TIFFForceStrileArrayWriting TIFFFreeDirectory TIFFGetBitRevTable TIFFGetClientInfo @@ -49,6 +51,10 @@ EXPORTS TIFFAccessTagMethods TIFFGetReadProc TIFFGetSeekProc TIFFGetSizeProc + TIFFGetStrileByteCount + TIFFGetStrileByteCountWithErr + TIFFGetStrileOffset + TIFFGetStrileOffsetWithErr TIFFGetTagListCount TIFFGetTagListEntry TIFFGetUnmapFileProc @@ -82,6 +88,7 @@ EXPORTS TIFFAccessTagMethods TIFFReadEXIFDirectory TIFFReadEncodedStrip TIFFReadEncodedTile + TIFFReadFromUserBuffer TIFFReadRGBAImage TIFFReadRGBAImageOriented TIFFReadRGBAStrip diff --git a/src/3rdparty/libtiff/libtiff/mkg3states.c b/src/3rdparty/libtiff/libtiff/mkg3states.c index 54fc059..2cb9174 100644 --- a/src/3rdparty/libtiff/libtiff/mkg3states.c +++ b/src/3rdparty/libtiff/libtiff/mkg3states.c @@ -40,7 +40,7 @@ #include "tif_fax3.h" #ifndef HAVE_GETOPT -extern int getopt(int, char**, char*); +extern int getopt(int argc, char * const argv[], const char *optstring); #endif #define streq(a,b) (strcmp(a,b) == 0) diff --git a/src/3rdparty/libtiff/libtiff/tif_aux.c b/src/3rdparty/libtiff/libtiff/tif_aux.c index 33fb8a4..8188db5 100644 --- a/src/3rdparty/libtiff/libtiff/tif_aux.c +++ b/src/3rdparty/libtiff/libtiff/tif_aux.c @@ -30,31 +30,28 @@ #include "tiffiop.h" #include "tif_predict.h" #include +#include uint32 _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where) { - uint32 bytes = first * second; - - if (second && bytes / second != first) { + if (second && first > TIFF_UINT32_MAX / second) { TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); - bytes = 0; + return 0; } - return bytes; + return first * second; } uint64 _TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where) { - uint64 bytes = first * second; - - if (second && bytes / second != first) { + if (second && first > TIFF_UINT64_MAX / second) { TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); - bytes = 0; + return 0; } - return bytes; + return first * second; } tmsize_t @@ -396,6 +393,15 @@ _TIFFUInt64ToDouble(uint64 ui64) } } +float _TIFFClampDoubleToFloat( double val ) +{ + if( val > FLT_MAX ) + return FLT_MAX; + if( val < -FLT_MAX ) + return -FLT_MAX; + return (float)val; +} + int _TIFFSeekOK(TIFF* tif, toff_t off) { /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ diff --git a/src/3rdparty/libtiff/libtiff/tif_config.h b/src/3rdparty/libtiff/libtiff/tif_config.h index 7306e52..73c602f 100644 --- a/src/3rdparty/libtiff/libtiff/tif_config.h +++ b/src/3rdparty/libtiff/libtiff/tif_config.h @@ -32,7 +32,7 @@ packages produce RGBA files but don't mark the alpha properly. */ /* #undef DEFAULT_EXTRASAMPLE_AS_ALPHA */ -/* enable deferred strip/tile offset/size loading (experimental) */ +/* enable deferred strip/tile offset/size loading */ /* #undef DEFER_STRILE_LOAD */ /* Define to 1 if you have the header file. */ diff --git a/src/3rdparty/libtiff/libtiff/tif_config.h.in b/src/3rdparty/libtiff/libtiff/tif_config.h.in index eae07aa..523da3e 100644 --- a/src/3rdparty/libtiff/libtiff/tif_config.h.in +++ b/src/3rdparty/libtiff/libtiff/tif_config.h.in @@ -21,7 +21,7 @@ packages produce RGBA files but don't mark the alpha properly. */ #undef DEFAULT_EXTRASAMPLE_AS_ALPHA -/* enable deferred strip/tile offset/size loading (experimental) */ +/* enable deferred strip/tile offset/size loading */ #undef DEFER_STRILE_LOAD /* Define to 1 if you have the header file. */ diff --git a/src/3rdparty/libtiff/libtiff/tif_dir.c b/src/3rdparty/libtiff/libtiff/tif_dir.c index 6f0b487..1e0a76c 100644 --- a/src/3rdparty/libtiff/libtiff/tif_dir.c +++ b/src/3rdparty/libtiff/libtiff/tif_dir.c @@ -29,7 +29,6 @@ * (and also some miscellaneous stuff) */ #include "tiffiop.h" -#include /* * These are used in the backwards compatibility code... @@ -47,8 +46,8 @@ setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size) *vpp = 0; } if (vp) { - tmsize_t bytes = (tmsize_t)(nmemb * elem_size); - if (elem_size && bytes / elem_size == nmemb) + tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL); + if (bytes) *vpp = (void*) _TIFFmalloc(bytes); if (*vpp) _TIFFmemcpy(*vpp, vp, bytes); @@ -88,13 +87,15 @@ setDoubleArrayOneValue(double** vpp, double value, size_t nmemb) * Install extra samples information. */ static int -setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) +setExtraSamples(TIFF* tif, va_list ap, uint32* v) { /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */ #define EXTRASAMPLE_COREL_UNASSALPHA 999 uint16* va; uint32 i; + TIFFDirectory* td = &tif->tif_dir; + static const char module[] = "setExtraSamples"; *v = (uint16) va_arg(ap, uint16_vap); if ((uint16) *v > td->td_samplesperpixel) @@ -116,6 +117,18 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v) return 0; } } + + if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) && + !(td->td_samplesperpixel - td->td_extrasamples > 1)) + { + TIFFWarningExt(tif->tif_clientdata,module, + "ExtraSamples tag value is changing, " + "but TransferFunction was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION); + _TIFFfree(td->td_transferfunction[0]); + td->td_transferfunction[0] = NULL; + } + td->td_extrasamples = (uint16) *v; _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); return 1; @@ -153,15 +166,6 @@ bad: return (0); } -static float TIFFClampDoubleToFloat( double val ) -{ - if( val > FLT_MAX ) - return FLT_MAX; - if( val < -FLT_MAX ) - return -FLT_MAX; - return (float)val; -} - static int _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) { @@ -285,6 +289,18 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) _TIFFfree(td->td_smaxsamplevalue); td->td_smaxsamplevalue = NULL; } + /* Test if 3 transfer functions instead of just one are now needed + See http://bugzilla.maptools.org/show_bug.cgi?id=2820 */ + if( td->td_transferfunction[0] != NULL && (v - td->td_extrasamples > 1) && + !(td->td_samplesperpixel - td->td_extrasamples > 1)) + { + TIFFWarningExt(tif->tif_clientdata,module, + "SamplesPerPixel tag value is changing, " + "but TransferFunction was read with a different value. Cancelling it"); + TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION); + _TIFFfree(td->td_transferfunction[0]); + td->td_transferfunction[0] = NULL; + } } td->td_samplesperpixel = (uint16) v; break; @@ -320,13 +336,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) dblval = va_arg(ap, double); if( dblval < 0 ) goto badvaluedouble; - td->td_xresolution = TIFFClampDoubleToFloat( dblval ); + td->td_xresolution = _TIFFClampDoubleToFloat( dblval ); break; case TIFFTAG_YRESOLUTION: dblval = va_arg(ap, double); if( dblval < 0 ) goto badvaluedouble; - td->td_yresolution = TIFFClampDoubleToFloat( dblval ); + td->td_yresolution = _TIFFClampDoubleToFloat( dblval ); break; case TIFFTAG_PLANARCONFIG: v = (uint16) va_arg(ap, uint16_vap); @@ -335,10 +351,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) td->td_planarconfig = (uint16) v; break; case TIFFTAG_XPOSITION: - td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); + td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) ); break; case TIFFTAG_YPOSITION: - td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); + td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) ); break; case TIFFTAG_RESOLUTIONUNIT: v = (uint16) va_arg(ap, uint16_vap); @@ -361,7 +377,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32); break; case TIFFTAG_EXTRASAMPLES: - if (!setExtraSamples(td, ap, &v)) + if (!setExtraSamples(tif, ap, &v)) goto badvalue; break; case TIFFTAG_MATTEING: @@ -684,7 +700,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) case TIFF_SRATIONAL: case TIFF_FLOAT: { - float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); + float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double)); _TIFFmemcpy(val, &v2, tv_size); } break; @@ -1002,12 +1018,12 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap) case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: _TIFFFillStriles( tif ); - *va_arg(ap, uint64**) = td->td_stripoffset; + *va_arg(ap, uint64**) = td->td_stripoffset_p; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: _TIFFFillStriles( tif ); - *va_arg(ap, uint64**) = td->td_stripbytecount; + *va_arg(ap, uint64**) = td->td_stripbytecount_p; break; case TIFFTAG_MATTEING: *va_arg(ap, uint16*) = @@ -1266,8 +1282,9 @@ TIFFFreeDirectory(TIFF* tif) CleanupField(td_transferfunction[0]); CleanupField(td_transferfunction[1]); CleanupField(td_transferfunction[2]); - CleanupField(td_stripoffset); - CleanupField(td_stripbytecount); + CleanupField(td_stripoffset_p); + CleanupField(td_stripbytecount_p); + td->td_stripoffsetbyteallocsize = 0; TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); @@ -1280,10 +1297,8 @@ TIFFFreeDirectory(TIFF* tif) td->td_customValueCount = 0; CleanupField(td_customValues); -#if defined(DEFER_STRILE_LOAD) _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); -#endif } #undef CleanupField @@ -1371,7 +1386,9 @@ TIFFDefaultDirectory(TIFF* tif) td->td_tilewidth = 0; td->td_tilelength = 0; td->td_tiledepth = 1; +#ifdef STRIPBYTECOUNTSORTED_UNUSED td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ +#endif td->td_resolutionunit = RESUNIT_INCH; td->td_sampleformat = SAMPLEFORMAT_UINT; td->td_imagedepth = 1; diff --git a/src/3rdparty/libtiff/libtiff/tif_dir.h b/src/3rdparty/libtiff/libtiff/tif_dir.h index b2f5e69..e7f0667 100644 --- a/src/3rdparty/libtiff/libtiff/tif_dir.h +++ b/src/3rdparty/libtiff/libtiff/tif_dir.h @@ -58,6 +58,7 @@ typedef struct { uint32 toff_long; uint64 toff_long8; } tdir_offset; /* either offset or the data itself if fits */ + uint8 tdir_ignore; /* flag status to ignore tag when parsing tags in tif_dirread.c */ } TIFFDirEntry; /* @@ -97,13 +98,14 @@ typedef struct { * number of striles */ uint32 td_stripsperimage; uint32 td_nstrips; /* size of offset & bytecount arrays */ - uint64* td_stripoffset; - uint64* td_stripbytecount; + uint64* td_stripoffset_p; /* should be accessed with TIFFGetStrileOffset */ + uint64* td_stripbytecount_p; /* should be accessed with TIFFGetStrileByteCount */ + uint32 td_stripoffsetbyteallocsize; /* number of elements currently allocated for td_stripoffset/td_stripbytecount. Only used if TIFF_LAZYSTRILELOAD is set */ +#ifdef STRIPBYTECOUNTSORTED_UNUSED int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */ -#if defined(DEFER_STRILE_LOAD) +#endif TIFFDirEntry td_stripoffset_entry; /* for deferred loading */ TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */ -#endif uint16 td_nsubifd; uint64* td_subifd; /* YCbCr parameters */ @@ -118,6 +120,8 @@ typedef struct { int td_customValueCount; TIFFTagValue *td_customValues; + + unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */ } TIFFDirectory; /* diff --git a/src/3rdparty/libtiff/libtiff/tif_dirread.c b/src/3rdparty/libtiff/libtiff/tif_dirread.c index e80a3b1..6f90941 100644 --- a/src/3rdparty/libtiff/libtiff/tif_dirread.c +++ b/src/3rdparty/libtiff/libtiff/tif_dirread.c @@ -29,9 +29,6 @@ */ /* Suggested pending improvements: - * - add a field 'ignore' to the TIFFDirEntry structure, to flag status, - * eliminating current use of the IGNORE value, and therefore eliminating - * current irrational behaviour on tags with tag id code 0 * - add a field 'field_info' to the TIFFDirEntry structure, and set that with * the pointer to the appropriate TIFFField structure early on in * TIFFReadDirectory, so as to eliminate current possibly repetitive lookup. @@ -41,9 +38,13 @@ #include #include -#define IGNORE 0 /* tag placeholder used below */ #define FAILED_FII ((uint32) -1) +/* + * Largest 64-bit signed integer value. + */ +#define TIFF_INT64_MAX ((int64)(TIFF_UINT64_MAX >> 1)) + #ifdef HAVE_IEEEFP # define TIFFCvtIEEEFloatToNative(tif, n, fp) # define TIFFCvtIEEEDoubleToNative(tif, n, dp) @@ -164,6 +165,7 @@ static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*, int recover); static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp); static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*); static void ChopUpSingleUncompressedStrip(TIFF*); +static void TryChopUpUncompressedBigTiff(TIFF*); static uint64 TIFFReadUInt64(const uint8 *value); static int _TIFFGetMaxColorChannels(uint16 photometric); @@ -205,6 +207,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* di switch (direntry->tdir_type) { case TIFF_BYTE: + case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with field_readcount==1 */ TIFFReadDirEntryCheckedByte(tif,direntry,value); return(TIFFReadDirEntryErrOk); case TIFF_SBYTE: @@ -3287,11 +3290,6 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value) return(TIFFReadDirEntryErrOk); } -/* - * Largest 32-bit unsigned integer value. - */ -#define TIFF_UINT32_MAX 0xFFFFFFFFU - static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongLong8(uint64 value) { @@ -3310,8 +3308,6 @@ TIFFReadDirEntryCheckRangeLongSlong8(int64 value) return(TIFFReadDirEntryErrOk); } -#undef TIFF_UINT32_MAX - static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong(uint32 value) { @@ -3377,11 +3373,6 @@ TIFFReadDirEntryCheckRangeLong8Slong8(int64 value) return(TIFFReadDirEntryErrOk); } -/* - * Largest 64-bit signed integer value. - */ -#define TIFF_INT64_MAX ((int64)(((uint64) ~0) >> 1)) - static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value) { @@ -3391,8 +3382,6 @@ TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value) return(TIFFReadDirEntryErrOk); } -#undef TIFF_INT64_MAX - static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest) { @@ -3405,13 +3394,13 @@ TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest) } else { size_t ma,mb; ma=(size_t)offset; + if( (uint64)ma!=offset || + ma > (~(size_t)0) - (size_t)size ) + { + return TIFFReadDirEntryErrIo; + } mb=ma+size; - if (((uint64)ma!=offset) - || (mb < ma) - || (mb - ma != (size_t) size) - || (mb < (size_t)size) - || (mb > (size_t)tif->tif_size) - ) + if (mb > (size_t)tif->tif_size) return(TIFFReadDirEntryErrIo); _TIFFmemcpy(dest,tif->tif_base+ma,size); } @@ -3534,6 +3523,49 @@ static int _TIFFGetMaxColorChannels( uint16 photometric ) } } +static int ByteCountLooksBad(TIFF* tif) +{ + /* + * Assume we have wrong StripByteCount value (in case + * of single strip) in following cases: + * - it is equal to zero along with StripOffset; + * - it is larger than file itself (in case of uncompressed + * image); + * - it is smaller than the size of the bytes per row + * multiplied on the number of rows. The last case should + * not be checked in the case of writing new image, + * because we may do not know the exact strip size + * until the whole image will be written and directory + * dumped out. + */ + uint64 bytecount = TIFFGetStrileByteCount(tif, 0); + uint64 offset = TIFFGetStrileOffset(tif, 0); + uint64 filesize; + + if( offset == 0 ) + return 0; + if (bytecount == 0) + return 1; + if ( tif->tif_dir.td_compression != COMPRESSION_NONE ) + return 0; + filesize = TIFFGetFileSize(tif); + if( offset <= filesize && bytecount > filesize - offset ) + return 1; + if( tif->tif_mode == O_RDONLY ) + { + uint64 scanlinesize = TIFFScanlineSize64(tif); + if( tif->tif_dir.td_imagelength > 0 && + scanlinesize > TIFF_UINT64_MAX / tif->tif_dir.td_imagelength ) + { + return 1; + } + if( bytecount < scanlinesize * tif->tif_dir.td_imagelength) + return 1; + } + return 0; +} + + /* * Read the next TIFF directory from a file and convert it to the internal * format. We read directories sequentially. @@ -3580,14 +3612,17 @@ TIFFReadDirectory(TIFF* tif) uint16 nb; for (na=ma+1, nb=mb+1; nbtdir_tag==na->tdir_tag) - na->tdir_tag=IGNORE; + if (ma->tdir_tag == na->tdir_tag) { + na->tdir_ignore = TRUE; + } } } } tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ tif->tif_flags &= ~TIFF_BUF4WRITE; /* reset before new dir */ + tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS; + /* free any old stuff and reinit */ TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); @@ -3620,7 +3655,7 @@ TIFFReadDirectory(TIFF* tif) { if (!TIFFFetchNormalTag(tif,dp,0)) goto bad; - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION); if (dp) @@ -3643,7 +3678,7 @@ TIFFReadDirectory(TIFF* tif) } if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value)) goto bad; - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } else { @@ -3655,7 +3690,7 @@ TIFFReadDirectory(TIFF* tif) */ for (di=0, dp=dir; ditdir_tag!=IGNORE) + if (!dp->tdir_ignore) { TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); if (fii == FAILED_FII) @@ -3663,8 +3698,8 @@ TIFFReadDirectory(TIFF* tif) TIFFWarningExt(tif->tif_clientdata, module, "Unknown field with tag %d (0x%x) encountered", dp->tdir_tag,dp->tdir_tag); - /* the following knowingly leaks the - anonymous field structure */ + /* the following knowingly leaks the + anonymous field structure */ if (!_TIFFMergeFields(tif, _TIFFCreateAnonField(tif, dp->tdir_tag, @@ -3675,18 +3710,18 @@ TIFFReadDirectory(TIFF* tif) "Registering anonymous field with tag %d (0x%x) failed", dp->tdir_tag, dp->tdir_tag); - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } else { TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); assert(fii != FAILED_FII); } } } - if (dp->tdir_tag!=IGNORE) + if (!dp->tdir_ignore) { fip=tif->tif_fields[fii]; if (fip->field_bit==FIELD_IGNORE) - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; else { switch (dp->tdir_tag) @@ -3708,12 +3743,12 @@ TIFFReadDirectory(TIFF* tif) case TIFFTAG_EXTRASAMPLES: if (!TIFFFetchNormalTag(tif,dp,0)) goto bad; - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; + break; + default: + if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) ) + dp->tdir_ignore = TRUE; break; - default: - if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) ) - dp->tdir_tag=IGNORE; - break; } } } @@ -3729,8 +3764,8 @@ TIFFReadDirectory(TIFF* tif) if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&& (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE)) { - if (!_TIFFFillStriles(tif)) - goto bad; + if (!_TIFFFillStriles(tif)) + goto bad; dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS); if ((dp!=0)&&(dp->tdir_count==1)) { @@ -3802,190 +3837,200 @@ TIFFReadDirectory(TIFF* tif) */ for (di=0, dp=dir; ditdir_tag) - { - case IGNORE: - break; - case TIFFTAG_MINSAMPLEVALUE: - case TIFFTAG_MAXSAMPLEVALUE: - case TIFFTAG_BITSPERSAMPLE: - case TIFFTAG_DATATYPE: - case TIFFTAG_SAMPLEFORMAT: - /* - * The MinSampleValue, MaxSampleValue, BitsPerSample - * DataType and SampleFormat tags are supposed to be - * written as one value/sample, but some vendors - * incorrectly write one value only -- so we accept - * that as well (yuck). Other vendors write correct - * value for NumberOfSamples, but incorrect one for - * BitsPerSample and friends, and we will read this - * too. - */ - { - uint16 value; - enum TIFFReadDirEntryErr err; - err=TIFFReadDirEntryShort(tif,dp,&value); - if (err==TIFFReadDirEntryErrCount) - err=TIFFReadDirEntryPersampleShort(tif,dp,&value); - if (err!=TIFFReadDirEntryErrOk) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); - goto bad; - } - if (!TIFFSetField(tif,dp->tdir_tag,value)) - goto bad; - if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE ) - bitspersample_read = TRUE; - } - break; - case TIFFTAG_SMINSAMPLEVALUE: - case TIFFTAG_SMAXSAMPLEVALUE: - { - - double *data = NULL; - enum TIFFReadDirEntryErr err; - uint32 saved_flags; - int m; - if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel) - err = TIFFReadDirEntryErrCount; - else - err = TIFFReadDirEntryDoubleArray(tif, dp, &data); - if (err!=TIFFReadDirEntryErrOk) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); - goto bad; - } - saved_flags = tif->tif_flags; - tif->tif_flags |= TIFF_PERSAMPLE; - m = TIFFSetField(tif,dp->tdir_tag,data); - tif->tif_flags = saved_flags; - _TIFFfree(data); - if (!m) - goto bad; - } - break; - case TIFFTAG_STRIPOFFSETS: - case TIFFTAG_TILEOFFSETS: -#if defined(DEFER_STRILE_LOAD) - _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), - dp, sizeof(TIFFDirEntry) ); -#else - if( tif->tif_dir.td_stripoffset != NULL ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "tif->tif_dir.td_stripoffset is " - "already allocated. Likely duplicated " - "StripOffsets/TileOffsets tag"); - goto bad; - } - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset)) - goto bad; -#endif - break; - case TIFFTAG_STRIPBYTECOUNTS: - case TIFFTAG_TILEBYTECOUNTS: -#if defined(DEFER_STRILE_LOAD) - _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), - dp, sizeof(TIFFDirEntry) ); -#else - if( tif->tif_dir.td_stripbytecount != NULL ) - { - TIFFErrorExt(tif->tif_clientdata, module, - "tif->tif_dir.td_stripbytecount is " - "already allocated. Likely duplicated " - "StripByteCounts/TileByteCounts tag"); - goto bad; - } - if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount)) - goto bad; -#endif - break; - case TIFFTAG_COLORMAP: - case TIFFTAG_TRANSFERFUNCTION: - { - enum TIFFReadDirEntryErr err; - uint32 countpersample; - uint32 countrequired; - uint32 incrementpersample; - uint16* value=NULL; - /* It would be dangerous to instantiate those tag values */ - /* since if td_bitspersample has not yet been read (due to */ - /* unordered tags), it could be read afterwards with a */ - /* values greater than the default one (1), which may cause */ - /* crashes in user code */ - if( !bitspersample_read ) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFWarningExt(tif->tif_clientdata,module, - "Ignoring %s since BitsPerSample tag not found", - fip ? fip->field_name : "unknown tagname"); - continue; - } - /* ColorMap or TransferFunction for high bit */ - /* depths do not make much sense and could be */ - /* used as a denial of service vector */ - if (tif->tif_dir.td_bitspersample > 24) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFWarningExt(tif->tif_clientdata,module, - "Ignoring %s because BitsPerSample=%d>24", - fip ? fip->field_name : "unknown tagname", - tif->tif_dir.td_bitspersample); - continue; - } - countpersample=(1U<tif_dir.td_bitspersample); - if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) + if (!dp->tdir_ignore) { + switch (dp->tdir_tag) + { + case TIFFTAG_MINSAMPLEVALUE: + case TIFFTAG_MAXSAMPLEVALUE: + case TIFFTAG_BITSPERSAMPLE: + case TIFFTAG_DATATYPE: + case TIFFTAG_SAMPLEFORMAT: + /* + * The MinSampleValue, MaxSampleValue, BitsPerSample + * DataType and SampleFormat tags are supposed to be + * written as one value/sample, but some vendors + * incorrectly write one value only -- so we accept + * that as well (yuck). Other vendors write correct + * value for NumberOfSamples, but incorrect one for + * BitsPerSample and friends, and we will read this + * too. + */ { - countrequired=countpersample; - incrementpersample=0; + uint16 value; + enum TIFFReadDirEntryErr err; + err=TIFFReadDirEntryShort(tif,dp,&value); + if (err==TIFFReadDirEntryErrCount) + err=TIFFReadDirEntryPersampleShort(tif,dp,&value); + if (err!=TIFFReadDirEntryErrOk) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); + goto bad; + } + if (!TIFFSetField(tif,dp->tdir_tag,value)) + goto bad; + if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE ) + bitspersample_read = TRUE; } - else + break; + case TIFFTAG_SMINSAMPLEVALUE: + case TIFFTAG_SMAXSAMPLEVALUE: { - countrequired=3*countpersample; - incrementpersample=countpersample; + + double *data = NULL; + enum TIFFReadDirEntryErr err; + uint32 saved_flags; + int m; + if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel) + err = TIFFReadDirEntryErrCount; + else + err = TIFFReadDirEntryDoubleArray(tif, dp, &data); + if (err!=TIFFReadDirEntryErrOk) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0); + goto bad; + } + saved_flags = tif->tif_flags; + tif->tif_flags |= TIFF_PERSAMPLE; + m = TIFFSetField(tif,dp->tdir_tag,data); + tif->tif_flags = saved_flags; + _TIFFfree(data); + if (!m) + goto bad; } - if (dp->tdir_count!=(uint64)countrequired) - err=TIFFReadDirEntryErrCount; - else - err=TIFFReadDirEntryShortArray(tif,dp,&value); - if (err!=TIFFReadDirEntryErrOk) - { - fip = TIFFFieldWithTag(tif,dp->tdir_tag); - TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1); - } - else + break; + case TIFFTAG_STRIPOFFSETS: + case TIFFTAG_TILEOFFSETS: + _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry), + dp, sizeof(TIFFDirEntry) ); + break; + case TIFFTAG_STRIPBYTECOUNTS: + case TIFFTAG_TILEBYTECOUNTS: + _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry), + dp, sizeof(TIFFDirEntry) ); + break; + case TIFFTAG_COLORMAP: + case TIFFTAG_TRANSFERFUNCTION: { - TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample); - _TIFFfree(value); + enum TIFFReadDirEntryErr err; + uint32 countpersample; + uint32 countrequired; + uint32 incrementpersample; + uint16* value=NULL; + /* It would be dangerous to instantiate those tag values */ + /* since if td_bitspersample has not yet been read (due to */ + /* unordered tags), it could be read afterwards with a */ + /* values greater than the default one (1), which may cause */ + /* crashes in user code */ + if( !bitspersample_read ) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFWarningExt(tif->tif_clientdata,module, + "Ignoring %s since BitsPerSample tag not found", + fip ? fip->field_name : "unknown tagname"); + continue; + } + /* ColorMap or TransferFunction for high bit */ + /* depths do not make much sense and could be */ + /* used as a denial of service vector */ + if (tif->tif_dir.td_bitspersample > 24) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFWarningExt(tif->tif_clientdata,module, + "Ignoring %s because BitsPerSample=%d>24", + fip ? fip->field_name : "unknown tagname", + tif->tif_dir.td_bitspersample); + continue; + } + countpersample=(1U<tif_dir.td_bitspersample); + if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample)) + { + countrequired=countpersample; + incrementpersample=0; + } + else + { + countrequired=3*countpersample; + incrementpersample=countpersample; + } + if (dp->tdir_count!=(uint64)countrequired) + err=TIFFReadDirEntryErrCount; + else + err=TIFFReadDirEntryShortArray(tif,dp,&value); + if (err!=TIFFReadDirEntryErrOk) + { + fip = TIFFFieldWithTag(tif,dp->tdir_tag); + TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1); + } + else + { + TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample); + _TIFFfree(value); + } } - } - break; + break; /* BEGIN REV 4.0 COMPATIBILITY */ - case TIFFTAG_OSUBFILETYPE: - { - uint16 valueo; - uint32 value; - if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk) + case TIFFTAG_OSUBFILETYPE: { - switch (valueo) + uint16 valueo; + uint32 value; + if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk) { - case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break; - case OFILETYPE_PAGE: value=FILETYPE_PAGE; break; - default: value=0; break; + switch (valueo) + { + case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break; + case OFILETYPE_PAGE: value=FILETYPE_PAGE; break; + default: value=0; break; + } + if (value!=0) + TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value); } - if (value!=0) - TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value); } - } - break; + break; /* END REV 4.0 COMPATIBILITY */ - default: - (void) TIFFFetchNormalTag(tif, dp, TRUE); - break; - } - } + default: + (void) TIFFFetchNormalTag(tif, dp, TRUE); + break; + } + } /* -- if (!dp->tdir_ignore) */ + } /* -- for-loop -- */ + + if( tif->tif_mode == O_RDWR && + tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && + tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 ) + { + /* Directory typically created with TIFFDeferStrileArrayWriting() */ + TIFFSetupStrips(tif); + } + else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) ) + { + if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 ) + { + if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry), + tif->tif_dir.td_nstrips, + &tif->tif_dir.td_stripoffset_p)) + { + goto bad; + } + } + if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 ) + { + if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry), + tif->tif_dir.td_nstrips, + &tif->tif_dir.td_stripbytecount_p)) + { + goto bad; + } + } + } + /* * OJPEG hack: * - If a) compression is OJPEG, and b) photometric tag is missing, @@ -4128,33 +4173,10 @@ TIFFReadDirectory(TIFF* tif) "\"StripByteCounts\" field, calculating from imagelength"); if (EstimateStripByteCounts(tif, dir, dircount) < 0) goto bad; - /* - * Assume we have wrong StripByteCount value (in case - * of single strip) in following cases: - * - it is equal to zero along with StripOffset; - * - it is larger than file itself (in case of uncompressed - * image); - * - it is smaller than the size of the bytes per row - * multiplied on the number of rows. The last case should - * not be checked in the case of writing new image, - * because we may do not know the exact strip size - * until the whole image will be written and directory - * dumped out. - */ - #define BYTECOUNTLOOKSBAD \ - ( (tif->tif_dir.td_stripbytecount[0] == 0 && tif->tif_dir.td_stripoffset[0] != 0) || \ - (tif->tif_dir.td_compression == COMPRESSION_NONE && \ - (tif->tif_dir.td_stripoffset[0] <= TIFFGetFileSize(tif) && \ - tif->tif_dir.td_stripbytecount[0] > TIFFGetFileSize(tif) - tif->tif_dir.td_stripoffset[0])) || \ - (tif->tif_mode == O_RDONLY && \ - tif->tif_dir.td_compression == COMPRESSION_NONE && \ - tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) ) } else if (tif->tif_dir.td_nstrips == 1 && !(tif->tif_flags&TIFF_ISTILED) - && _TIFFFillStriles(tif) - && tif->tif_dir.td_stripoffset[0] != 0 - && BYTECOUNTLOOKSBAD) { + && ByteCountLooksBad(tif)) { /* * XXX: Plexus (and others) sometimes give a value of * zero for a tag when they don't know what the @@ -4166,13 +4188,13 @@ TIFFReadDirectory(TIFF* tif) if(EstimateStripByteCounts(tif, dir, dircount) < 0) goto bad; -#if !defined(DEFER_STRILE_LOAD) - } else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG + } else if (!(tif->tif_flags&TIFF_DEFERSTRILELOAD) + && tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG && tif->tif_dir.td_nstrips > 2 && tif->tif_dir.td_compression == COMPRESSION_NONE - && tif->tif_dir.td_stripbytecount[0] != tif->tif_dir.td_stripbytecount[1] - && tif->tif_dir.td_stripbytecount[0] != 0 - && tif->tif_dir.td_stripbytecount[1] != 0 ) { + && TIFFGetStrileByteCount(tif, 0) != TIFFGetStrileByteCount(tif, 1) + && TIFFGetStrileByteCount(tif, 0) != 0 + && TIFFGetStrileByteCount(tif, 1) != 0 ) { /* * XXX: Some vendors fill StripByteCount array with * absolutely wrong values (it can be equal to @@ -4187,7 +4209,6 @@ TIFFReadDirectory(TIFF* tif) "Wrong \"StripByteCounts\" field, ignoring and calculating from imagelength"); if (EstimateStripByteCounts(tif, dir, dircount) < 0) goto bad; -#endif /* !defined(DEFER_STRILE_LOAD) */ } } if (dir) @@ -4202,26 +4223,27 @@ TIFFReadDirectory(TIFF* tif) else tif->tif_dir.td_maxsamplevalue = (uint16)((1L<tif_dir.td_bitspersample)-1); } + +#ifdef STRIPBYTECOUNTSORTED_UNUSED /* * XXX: We can optimize checking for the strip bounds using the sorted * bytecounts array. See also comments for TIFFAppendToStrip() * function in tif_write.c. */ -#if !defined(DEFER_STRILE_LOAD) - if (tif->tif_dir.td_nstrips > 1) { + if (!(tif->tif_flags&TIFF_DEFERSTRILELOAD) && tif->tif_dir.td_nstrips > 1) { uint32 strip; tif->tif_dir.td_stripbytecountsorted = 1; for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { - if (tif->tif_dir.td_stripoffset[strip - 1] > - tif->tif_dir.td_stripoffset[strip]) { + if (TIFFGetStrileOffset(tif, strip - 1) > + TIFFGetStrileOffset(tif, strip)) { tif->tif_dir.td_stripbytecountsorted = 0; break; } } } -#endif /* !defined(DEFER_STRILE_LOAD) */ - +#endif + /* * An opportunity for compression mode dependent tag fixup */ @@ -4240,11 +4262,20 @@ TIFFReadDirectory(TIFF* tif) (tif->tif_dir.td_nstrips==1)&& (tif->tif_dir.td_compression==COMPRESSION_NONE)&& ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP)) - { - if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount ) - return 0; - ChopUpSingleUncompressedStrip(tif); - } + { + ChopUpSingleUncompressedStrip(tif); + } + + /* There are also uncompressed striped files with strips larger than */ + /* 2 GB, which make them unfriendly with a lot of code. If possible, */ + /* try to expose smaller "virtual" strips. */ + if( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG && + tif->tif_dir.td_compression == COMPRESSION_NONE && + (tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP && + TIFFStripSize64(tif) > 0x7FFFFFFFUL ) + { + TryChopUpUncompressedBigTiff(tif); + } /* * Clear the dirty directory flag. @@ -4396,17 +4427,17 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, TIFFWarningExt(tif->tif_clientdata, module, "Registering anonymous field with tag %d (0x%x) failed", dp->tdir_tag, dp->tdir_tag); - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } else { TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii); assert( fii != FAILED_FII ); } } - if (dp->tdir_tag!=IGNORE) + if (!dp->tdir_ignore) { fip=tif->tif_fields[fii]; if (fip->field_bit==FIELD_IGNORE) - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; else { /* check data type */ @@ -4426,7 +4457,7 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, TIFFWarningExt(tif->tif_clientdata, module, "Wrong data type %d for \"%s\"; tag ignored", dp->tdir_type,fip->field_name); - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } else { @@ -4440,21 +4471,21 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff, else expected=(uint32)fip->field_readcount; if (!CheckDirCount(tif,dp,expected)) - dp->tdir_tag=IGNORE; + dp->tdir_ignore = TRUE; } } } - switch (dp->tdir_tag) - { - case IGNORE: - break; - case EXIFTAG_SUBJECTDISTANCE: - (void) TIFFFetchSubjectDistance(tif,dp); - break; - default: - (void) TIFFFetchNormalTag(tif, dp, TRUE); - break; - } + if (!dp->tdir_ignore) { + switch (dp->tdir_tag) + { + case EXIFTAG_SUBJECTDISTANCE: + (void)TIFFFetchSubjectDistance(tif, dp); + break; + default: + (void)TIFFFetchNormalTag(tif, dp, TRUE); + break; + } + } /*-- if (!dp->tdir_ignore) */ } } if (dir) @@ -4487,12 +4518,12 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) if( !_TIFFFillStrilesInternal( tif, 0 ) ) return -1; - if (td->td_stripbytecount) - _TIFFfree(td->td_stripbytecount); - td->td_stripbytecount = (uint64*) + if (td->td_stripbytecount_p) + _TIFFfree(td->td_stripbytecount_p); + td->td_stripbytecount_p = (uint64*) _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), "for \"StripByteCounts\" array"); - if( td->td_stripbytecount == NULL ) + if( td->td_stripbytecount_p == NULL ) return -1; if (td->td_compression != COMPRESSION_NONE) { @@ -4516,6 +4547,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) dp->tdir_type); return -1; } + if( dp->tdir_count > TIFF_UINT64_MAX / typewidth ) + return -1; datasize=(uint64)typewidth*dp->tdir_count; if (!(tif->tif_flags&TIFF_BIGTIFF)) { @@ -4527,6 +4560,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) if (datasize<=8) datasize=0; } + if( space > TIFF_UINT64_MAX - datasize ) + return -1; space+=datasize; } if( filesize < space ) @@ -4537,7 +4572,7 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) if (td->td_planarconfig == PLANARCONFIG_SEPARATE) space /= td->td_samplesperpixel; for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = space; + td->td_stripbytecount_p[strip] = space; /* * This gross hack handles the case were the offset to * the last strip is past the place where we think the strip @@ -4546,18 +4581,30 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount) * of data in the strip and trim this number back accordingly. */ strip--; - if (td->td_stripoffset[strip]+td->td_stripbytecount[strip] > filesize) - td->td_stripbytecount[strip] = filesize - td->td_stripoffset[strip]; + if (td->td_stripoffset_p[strip] > TIFF_UINT64_MAX - td->td_stripbytecount_p[strip]) + return -1; + if (td->td_stripoffset_p[strip]+td->td_stripbytecount_p[strip] > filesize) { + if( td->td_stripoffset_p[strip] >= filesize ) { + /* Not sure what we should in that case... */ + td->td_stripbytecount_p[strip] = 0; + } else { + td->td_stripbytecount_p[strip] = filesize - td->td_stripoffset_p[strip]; + } + } } else if (isTiled(tif)) { uint64 bytespertile = TIFFTileSize64(tif); for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = bytespertile; + td->td_stripbytecount_p[strip] = bytespertile; } else { uint64 rowbytes = TIFFScanlineSize64(tif); uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage; for (strip = 0; strip < td->td_nstrips; strip++) - td->td_stripbytecount[strip] = rowbytes * rowsperstrip; + { + if( rowbytes > 0 && rowsperstrip > TIFF_UINT64_MAX / rowbytes ) + return -1; + td->td_stripbytecount_p[strip] = rowbytes * rowsperstrip; + } } TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP)) @@ -4751,12 +4798,13 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, } } else { tmsize_t m; - tmsize_t off = (tmsize_t) tif->tif_diroff; - if ((uint64)off!=tif->tif_diroff) + tmsize_t off; + if (tif->tif_diroff > (uint64)TIFF_INT64_MAX) { TIFFErrorExt(tif->tif_clientdata,module,"Can not read TIFF directory count"); return(0); } + off = (tmsize_t) tif->tif_diroff; /* * Check for integer overflow when validating the dir_off, @@ -4874,6 +4922,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, mb=dir; for (n=0; ntdir_ignore = FALSE; if (tif->tif_flags&TIFF_SWAB) TIFFSwabShort((uint16*)ma); mb->tdir_tag=*(uint16*)ma; @@ -4888,6 +4937,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir, TIFFSwabLong((uint32*)ma); mb->tdir_count=(uint64)(*(uint32*)ma); ma+=sizeof(uint32); + mb->tdir_offset.toff_long8=0; *(uint32*)(&mb->tdir_offset)=*(uint32*)ma; ma+=sizeof(uint32); } @@ -5681,7 +5731,7 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) TIFFSwabArrayOfLong(m.i,2); if (m.i[0]==0) n=0.0; - else if (m.i[0]==0xFFFFFFFF) + else if (m.i[0]==0xFFFFFFFF || m.i[1]==0) /* * XXX: Numerator 0xFFFFFFFF means that we have infinite * distance. Indicate that with a negative floating point @@ -5699,6 +5749,75 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir) } } +static void allocChoppedUpStripArrays(TIFF* tif, uint32 nstrips, + uint64 stripbytes, uint32 rowsperstrip) +{ + TIFFDirectory *td = &tif->tif_dir; + uint64 bytecount; + uint64 offset; + uint64 last_offset; + uint64 last_bytecount; + uint32 i; + uint64 *newcounts; + uint64 *newoffsets; + + offset = TIFFGetStrileOffset(tif, 0); + last_offset = TIFFGetStrileOffset(tif, td->td_nstrips-1); + last_bytecount = TIFFGetStrileByteCount(tif, td->td_nstrips-1); + if( last_offset > TIFF_UINT64_MAX - last_bytecount || + last_offset + last_bytecount < offset ) + { + return; + } + bytecount = last_offset + last_bytecount - offset; + + newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), + "for chopped \"StripByteCounts\" array"); + newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), + "for chopped \"StripOffsets\" array"); + if (newcounts == NULL || newoffsets == NULL) { + /* + * Unable to allocate new strip information, give up and use + * the original one strip information. + */ + if (newcounts != NULL) + _TIFFfree(newcounts); + if (newoffsets != NULL) + _TIFFfree(newoffsets); + return; + } + + /* + * Fill the strip information arrays with new bytecounts and offsets + * that reflect the broken-up format. + */ + for (i = 0; i < nstrips; i++) + { + if (stripbytes > bytecount) + stripbytes = bytecount; + newcounts[i] = stripbytes; + newoffsets[i] = stripbytes ? offset : 0; + offset += stripbytes; + bytecount -= stripbytes; + } + + /* + * Replace old single strip info with multi-strip info. + */ + td->td_stripsperimage = td->td_nstrips = nstrips; + TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); + + _TIFFfree(td->td_stripbytecount_p); + _TIFFfree(td->td_stripoffset_p); + td->td_stripbytecount_p = newcounts; + td->td_stripoffset_p = newoffsets; +#ifdef STRIPBYTECOUNTSORTED_UNUSED + td->td_stripbytecountsorted = 1; +#endif + tif->tif_flags |= TIFF_CHOPPEDUPARRAYS; +} + + /* * Replace a single strip (tile) of uncompressed data by multiple strips * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for @@ -5714,19 +5833,16 @@ ChopUpSingleUncompressedStrip(TIFF* tif) uint32 rowblock; uint64 rowblockbytes; uint64 stripbytes; - uint32 strip; uint32 nstrips; uint32 rowsperstrip; - uint64* newcounts; - uint64* newoffsets; - bytecount = td->td_stripbytecount[0]; + bytecount = TIFFGetStrileByteCount(tif, 0); /* On a newly created file, just re-opened to be filled, we */ /* don't want strip chop to trigger as it is going to cause issues */ /* later ( StripOffsets and StripByteCounts improperly filled) . */ if( bytecount == 0 && tif->tif_mode != O_RDONLY ) return; - offset = td->td_stripoffset[0]; + offset = TIFFGetStrileByteCount(tif, 0); assert(td->td_planarconfig == PLANARCONFIG_CONTIG); if ((td->td_photometric == PHOTOMETRIC_YCBCR)&& (!isUpSampled(tif))) @@ -5769,98 +5885,503 @@ ChopUpSingleUncompressedStrip(TIFF* tif) return; } - newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), - "for chopped \"StripByteCounts\" array"); - newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64), - "for chopped \"StripOffsets\" array"); - if (newcounts == NULL || newoffsets == NULL) { - /* - * Unable to allocate new strip information, give up and use - * the original one strip information. - */ - if (newcounts != NULL) - _TIFFfree(newcounts); - if (newoffsets != NULL) - _TIFFfree(newoffsets); - return; - } - /* - * Fill the strip information arrays with new bytecounts and offsets - * that reflect the broken-up format. - */ - for (strip = 0; strip < nstrips; strip++) { - if (stripbytes > bytecount) - stripbytes = bytecount; - newcounts[strip] = stripbytes; - newoffsets[strip] = stripbytes ? offset : 0; - offset += stripbytes; - bytecount -= stripbytes; - } - /* - * Replace old single strip info with multi-strip info. - */ - td->td_stripsperimage = td->td_nstrips = nstrips; - TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip); - - _TIFFfree(td->td_stripbytecount); - _TIFFfree(td->td_stripoffset); - td->td_stripbytecount = newcounts; - td->td_stripoffset = newoffsets; - td->td_stripbytecountsorted = 1; + allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip); } -int _TIFFFillStriles( TIFF *tif ) + +/* + * Replace a file with contiguous strips > 2 GB of uncompressed data by + * multiple smaller strips. This is useful for + * dealing with large images or for dealing with machines with a limited + * amount memory. + */ +static void TryChopUpUncompressedBigTiff( TIFF* tif ) { - return _TIFFFillStrilesInternal( tif, 1 ); + TIFFDirectory *td = &tif->tif_dir; + uint32 rowblock; + uint64 rowblockbytes; + uint32 i; + uint64 stripsize; + uint32 rowblocksperstrip; + uint32 rowsperstrip; + uint64 stripbytes; + uint32 nstrips; + + stripsize = TIFFStripSize64(tif); + + assert( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG ); + assert( tif->tif_dir.td_compression == COMPRESSION_NONE ); + assert( (tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP ); + assert( stripsize > 0x7FFFFFFFUL ); + + /* On a newly created file, just re-opened to be filled, we */ + /* don't want strip chop to trigger as it is going to cause issues */ + /* later ( StripOffsets and StripByteCounts improperly filled) . */ + if( TIFFGetStrileByteCount(tif, 0) == 0 && tif->tif_mode != O_RDONLY ) + return; + + if ((td->td_photometric == PHOTOMETRIC_YCBCR)&& + (!isUpSampled(tif))) + rowblock = td->td_ycbcrsubsampling[1]; + else + rowblock = 1; + rowblockbytes = TIFFVStripSize64(tif, rowblock); + if( rowblockbytes == 0 || rowblockbytes > 0x7FFFFFFFUL ) + { + /* In case of file with gigantic width */ + return; + } + + /* Check that the strips are contiguous and of the expected size */ + for( i = 0; i < td->td_nstrips; i++ ) + { + if( i == td->td_nstrips - 1 ) + { + if( TIFFGetStrileByteCount(tif, i) < TIFFVStripSize64( + tif, td->td_imagelength - i * td->td_rowsperstrip ) ) + { + return; + } + } + else + { + if( TIFFGetStrileByteCount(tif, i) != stripsize ) + { + return; + } + if( i > 0 && TIFFGetStrileOffset(tif, i) != + TIFFGetStrileOffset(tif, i-1) + TIFFGetStrileByteCount(tif, i-1) ) + { + return; + } + } + } + + /* Aim for 512 MB strips (that will still be manageable by 32 bit builds */ + rowblocksperstrip = (uint32) (512 * 1024 * 1024 / rowblockbytes); + if( rowblocksperstrip == 0 ) + rowblocksperstrip = 1; + rowsperstrip = rowblocksperstrip * rowblock; + stripbytes = rowblocksperstrip * rowblockbytes; + assert( stripbytes <= 0x7FFFFFFFUL ); + + nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip); + if( nstrips == 0 ) + return; + + /* If we are going to allocate a lot of memory, make sure that the */ + /* file is as big as needed */ + if( tif->tif_mode == O_RDONLY && + nstrips > 1000000 ) + { + uint64 last_offset = TIFFGetStrileOffset(tif, td->td_nstrips-1); + uint64 filesize = TIFFGetFileSize(tif); + uint64 last_bytecount = TIFFGetStrileByteCount(tif, td->td_nstrips-1); + if( last_offset > filesize || + last_bytecount > filesize - last_offset ) + { + return; + } + } + + allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip); } -static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ) + +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static uint64 _TIFFUnsanitizedAddUInt64AndInt(uint64 a, int b) { -#if defined(DEFER_STRILE_LOAD) - register TIFFDirectory *td = &tif->tif_dir; - int return_value = 1; + return a + b; +} - if( td->td_stripoffset != NULL ) - return 1; +/* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around + * strip/tile of number strile. Also fetch the neighbouring values using a + * 4096 byte page size. + */ +static +int _TIFFPartialReadStripArray( TIFF* tif, TIFFDirEntry* dirent, + int strile, uint64* panVals ) +{ + static const char module[] = "_TIFFPartialReadStripArray"; +#define IO_CACHE_PAGE_SIZE 4096 + + size_t sizeofval; + const int bSwab = (tif->tif_flags & TIFF_SWAB) != 0; + int sizeofvalint; + uint64 nBaseOffset; + uint64 nOffset; + uint64 nOffsetStartPage; + uint64 nOffsetEndPage; + tmsize_t nToRead; + tmsize_t nRead; + uint64 nLastStripOffset; + int iStartBefore; + int i; + const uint32 arraySize = tif->tif_dir.td_stripoffsetbyteallocsize; + unsigned char buffer[2 * IO_CACHE_PAGE_SIZE]; + + assert( dirent->tdir_count > 4 ); + + if( dirent->tdir_type == TIFF_SHORT ) + { + sizeofval = sizeof(uint16); + } + else if( dirent->tdir_type == TIFF_LONG ) + { + sizeofval = sizeof(uint32); + } + else if( dirent->tdir_type == TIFF_LONG8 ) + { + sizeofval = sizeof(uint64); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Invalid type for [Strip|Tile][Offset/ByteCount] tag"); + panVals[strile] = 0; + return 0; + } + sizeofvalint = (int)(sizeofval); - if( td->td_stripoffset_entry.tdir_count == 0 ) + if( tif->tif_flags&TIFF_BIGTIFF ) + { + uint64 offset = dirent->tdir_offset.toff_long8; + if( bSwab ) + TIFFSwabLong8(&offset); + nBaseOffset = offset; + } + else + { + uint32 offset = dirent->tdir_offset.toff_long; + if( bSwab ) + TIFFSwabLong(&offset); + nBaseOffset = offset; + } + /* To avoid later unsigned integer overflows */ + if( nBaseOffset > (uint64)TIFF_INT64_MAX ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot read offset/size for strile %d", strile); + panVals[strile] = 0; + return 0; + } + nOffset = nBaseOffset + sizeofval * strile; + nOffsetStartPage = + (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE; + nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE; + + if( nOffset + sizeofval > nOffsetEndPage ) + nOffsetEndPage += IO_CACHE_PAGE_SIZE; +#undef IO_CACHE_PAGE_SIZE + + nLastStripOffset = nBaseOffset + arraySize * sizeofval; + if( nLastStripOffset < nOffsetEndPage ) + nOffsetEndPage = nLastStripOffset; + if( nOffsetStartPage >= nOffsetEndPage ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot read offset/size for strile %d", strile); + panVals[strile] = 0; + return 0; + } + if (!SeekOK(tif,nOffsetStartPage)) + { + panVals[strile] = 0; + return 0; + } + + nToRead = (tmsize_t)(nOffsetEndPage - nOffsetStartPage); + nRead = TIFFReadFile(tif, buffer, nToRead); + if( nRead < nToRead ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot read offset/size for strile around ~%d", strile); + return 0; + } + iStartBefore = -(int)((nOffset - nOffsetStartPage) / sizeofval); + if( strile + iStartBefore < 0 ) + iStartBefore = -strile; + for( i = iStartBefore; + (uint32)(strile + i) < arraySize && + _TIFFUnsanitizedAddUInt64AndInt(nOffset, (i + 1) * sizeofvalint) <= nOffsetEndPage; + ++i ) + { + if( sizeofval == sizeof(uint16) ) + { + uint16 val; + memcpy(&val, + buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint, + sizeof(val)); + if( bSwab ) + TIFFSwabShort(&val); + panVals[strile + i] = val; + } + else if( sizeofval == sizeof(uint32) ) + { + uint32 val; + memcpy(&val, + buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint, + sizeof(val)); + if( bSwab ) + TIFFSwabLong(&val); + panVals[strile + i] = val; + } + else + { + uint64 val; + memcpy(&val, + buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint, + sizeof(val)); + if( bSwab ) + TIFFSwabLong8(&val); + panVals[strile + i] = val; + } + } + return 1; +} + +static int _TIFFFetchStrileValue(TIFF* tif, + uint32 strile, + TIFFDirEntry* dirent, + uint64** parray) +{ + static const char module[] = "_TIFFFetchStrileValue"; + TIFFDirectory *td = &tif->tif_dir; + if( strile >= dirent->tdir_count ) + { + return 0; + } + if( strile >= td->td_stripoffsetbyteallocsize ) + { + uint32 nStripArrayAllocBefore = td->td_stripoffsetbyteallocsize; + uint32 nStripArrayAllocNew; + uint64 nArraySize64; + size_t nArraySize; + uint64* offsetArray; + uint64* bytecountArray; + + if( strile > 1000000 ) + { + uint64 filesize = TIFFGetFileSize(tif); + /* Avoid excessive memory allocation attempt */ + /* For such a big blockid we need at least a TIFF_LONG per strile */ + /* for the offset array. */ + if( strile > filesize / sizeof(uint32) ) + { + TIFFErrorExt(tif->tif_clientdata, module, "File too short"); return 0; + } + } - if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry), - td->td_nstrips,&td->td_stripoffset)) + if( td->td_stripoffsetbyteallocsize == 0 && + td->td_nstrips < 1024 * 1024 ) { - return_value = 0; + nStripArrayAllocNew = td->td_nstrips; + } + else + { +#define TIFF_MAX(a,b) (((a)>(b)) ? (a) : (b)) +#define TIFF_MIN(a,b) (((a)<(b)) ? (a) : (b)) + nStripArrayAllocNew = TIFF_MAX(strile + 1, 1024U * 512U ); + if( nStripArrayAllocNew < 0xFFFFFFFFU / 2 ) + nStripArrayAllocNew *= 2; + nStripArrayAllocNew = TIFF_MIN(nStripArrayAllocNew, td->td_nstrips); + } + assert( strile < nStripArrayAllocNew ); + nArraySize64 = (uint64)sizeof(uint64) * nStripArrayAllocNew; + nArraySize = (size_t)(nArraySize64); +#if SIZEOF_SIZE_T == 4 + if( nArraySize != nArraySize64 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot allocate strip offset and bytecount arrays"); + return 0; } +#endif + offsetArray = (uint64*)( + _TIFFrealloc( td->td_stripoffset_p, nArraySize ) ); + bytecountArray = (uint64*)( + _TIFFrealloc( td->td_stripbytecount_p, nArraySize ) ); + if( offsetArray ) + td->td_stripoffset_p = offsetArray; + if( bytecountArray ) + td->td_stripbytecount_p = bytecountArray; + if( offsetArray && bytecountArray ) + { + td->td_stripoffsetbyteallocsize = nStripArrayAllocNew; + /* Initialize new entries to ~0 / -1 */ + memset(td->td_stripoffset_p + nStripArrayAllocBefore, + 0xFF, + (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) * sizeof(uint64) ); + memset(td->td_stripbytecount_p + nStripArrayAllocBefore, + 0xFF, + (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) * sizeof(uint64) ); + } + else + { + TIFFErrorExt(tif->tif_clientdata, module, + "Cannot allocate strip offset and bytecount arrays"); + _TIFFfree(td->td_stripoffset_p); + td->td_stripoffset_p = NULL; + _TIFFfree(td->td_stripbytecount_p); + td->td_stripbytecount_p = NULL; + td->td_stripoffsetbyteallocsize = 0; + } + } + if( *parray == NULL || strile >= td->td_stripoffsetbyteallocsize ) + return 0; - if (loadStripByteCount && - !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), - td->td_nstrips,&td->td_stripbytecount)) + if( ~((*parray)[strile]) == 0 ) + { + if( !_TIFFPartialReadStripArray( tif, dirent, strile, *parray ) ) { - return_value = 0; + (*parray)[strile] = 0; + return 0; } + } - _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); - _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); + return 1; +} - if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) { - uint32 strip; +static uint64 _TIFFGetStrileOffsetOrByteCountValue(TIFF *tif, uint32 strile, + TIFFDirEntry* dirent, + uint64** parray, + int *pbErr) +{ + TIFFDirectory *td = &tif->tif_dir; + if( pbErr ) + *pbErr = 0; + if( (tif->tif_flags&TIFF_DEFERSTRILELOAD) && !(tif->tif_flags&TIFF_CHOPPEDUPARRAYS) ) + { + if( !(tif->tif_flags&TIFF_LAZYSTRILELOAD) || + /* If the values may fit in the toff_long/toff_long8 member */ + /* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */ + dirent->tdir_count <= 4 ) + { + if( !_TIFFFillStriles(tif) ) + { + if( pbErr ) + *pbErr = 1; + /* Do not return, as we want this function to always */ + /* return the same value if called several times with */ + /* the same arguments */ + } + } + else + { + if( !_TIFFFetchStrileValue(tif, strile, dirent, parray) ) + { + if( pbErr ) + *pbErr = 1; + return 0; + } + } + } + if( *parray == NULL || strile >= td->td_nstrips ) + { + if( pbErr ) + *pbErr = 1; + return 0; + } + return (*parray)[strile]; +} - tif->tif_dir.td_stripbytecountsorted = 1; - for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { - if (tif->tif_dir.td_stripoffset[strip - 1] > - tif->tif_dir.td_stripoffset[strip]) { - tif->tif_dir.td_stripbytecountsorted = 0; - break; - } - } - } +/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */ +uint64 TIFFGetStrileOffset(TIFF *tif, uint32 strile) +{ + return TIFFGetStrileOffsetWithErr(tif, strile, NULL); +} + +/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */ +uint64 TIFFGetStrileOffsetWithErr(TIFF *tif, uint32 strile, int *pbErr) +{ + TIFFDirectory *td = &tif->tif_dir; + return _TIFFGetStrileOffsetOrByteCountValue(tif, strile, + &(td->td_stripoffset_entry), + &(td->td_stripoffset_p), pbErr); +} + +/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */ +uint64 TIFFGetStrileByteCount(TIFF *tif, uint32 strile) +{ + return TIFFGetStrileByteCountWithErr(tif, strile, NULL); +} + +/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */ +uint64 TIFFGetStrileByteCountWithErr(TIFF *tif, uint32 strile, int *pbErr) +{ + TIFFDirectory *td = &tif->tif_dir; + return _TIFFGetStrileOffsetOrByteCountValue(tif, strile, + &(td->td_stripbytecount_entry), + &(td->td_stripbytecount_p), pbErr); +} - return return_value; -#else /* !defined(DEFER_STRILE_LOAD) */ - (void) tif; - (void) loadStripByteCount; + +int _TIFFFillStriles( TIFF *tif ) +{ + return _TIFFFillStrilesInternal( tif, 1 ); +} + +static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount ) +{ + register TIFFDirectory *td = &tif->tif_dir; + int return_value = 1; + + /* Do not do anything if TIFF_DEFERSTRILELOAD is not set */ + if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) || (tif->tif_flags&TIFF_CHOPPEDUPARRAYS) != 0 ) return 1; -#endif + + if( tif->tif_flags&TIFF_LAZYSTRILELOAD ) + { + /* In case of lazy loading, reload completely the arrays */ + _TIFFfree(td->td_stripoffset_p); + _TIFFfree(td->td_stripbytecount_p); + td->td_stripoffset_p = NULL; + td->td_stripbytecount_p = NULL; + td->td_stripoffsetbyteallocsize = 0; + tif->tif_flags &= ~TIFF_LAZYSTRILELOAD; + } + + /* If stripoffset array is already loaded, exit with success */ + if( td->td_stripoffset_p != NULL ) + return 1; + + /* If tdir_count was cancelled, then we already got there, but in error */ + if( td->td_stripoffset_entry.tdir_count == 0 ) + return 0; + + if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry), + td->td_nstrips,&td->td_stripoffset_p)) + { + return_value = 0; + } + + if (loadStripByteCount && + !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry), + td->td_nstrips,&td->td_stripbytecount_p)) + { + return_value = 0; + } + + _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); + _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); + +#ifdef STRIPBYTECOUNTSORTED_UNUSED + if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) { + uint32 strip; + + tif->tif_dir.td_stripbytecountsorted = 1; + for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) { + if (tif->tif_dir.td_stripoffset_p[strip - 1] > + tif->tif_dir.td_stripoffset_p[strip]) { + tif->tif_dir.td_stripbytecountsorted = 0; + break; + } + } + } +#endif + + return return_value; } diff --git a/src/3rdparty/libtiff/libtiff/tif_dirwrite.c b/src/3rdparty/libtiff/libtiff/tif_dirwrite.c index c15a28d..9e4d306 100644 --- a/src/3rdparty/libtiff/libtiff/tif_dirwrite.c +++ b/src/3rdparty/libtiff/libtiff/tif_dirwrite.c @@ -28,7 +28,6 @@ * Directory Write Support Routines. */ #include "tiffiop.h" -#include #ifdef HAVE_IEEEFP #define TIFFCvtNativeToIEEEFloat(tif, n, fp) @@ -182,6 +181,51 @@ TIFFWriteDirectory(TIFF* tif) return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); } +/* + * This is an advanced writing function that must be used in a particular + * sequence, and generally together with TIFFForceStrileArrayWriting(), + * to make its intended effect. Its aim is to modify the location + * where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file. + * More precisely, when TIFFWriteCheck() will be called, the tag entries for + * those arrays will be written with type = count = offset = 0 as a temporary + * value. + * + * Its effect is only valid for the current directory, and before + * TIFFWriteDirectory() is first called, and will be reset when + * changing directory. + * + * The typical sequence of calls is: + * TIFFOpen() + * [ TIFFCreateDirectory(tif) ] + * Set fields with calls to TIFFSetField(tif, ...) + * TIFFDeferStrileArrayWriting(tif) + * TIFFWriteCheck(tif, ...) + * TIFFWriteDirectory(tif) + * ... potentially create other directories and come back to the above directory + * TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file + * + * Returns 1 in case of success, 0 otherwise. + */ +int TIFFDeferStrileArrayWriting(TIFF* tif) +{ + static const char module[] = "TIFFDeferStrileArrayWriting"; + if (tif->tif_mode == O_RDONLY) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "File opened in read-only mode"); + return 0; + } + if( tif->tif_diroff != 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory has already been written"); + return 0; + } + + tif->tif_dir.td_deferstrilearraywriting = TRUE; + return 1; +} + /* * Similar to TIFFWriteDirectory(), writes the directory out * but leaves all data structures in memory so that it can be @@ -193,7 +237,7 @@ TIFFCheckpointDirectory(TIFF* tif) { int rc; /* Setup the strips arrays, if they haven't already been. */ - if (tif->tif_dir.td_stripoffset == NULL) + if (tif->tif_dir.td_stripoffset_p == NULL) (void) TIFFSetupStrips(tif); rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); @@ -528,12 +572,12 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) { if (!isTiled(tif)) { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p)) goto bad; } else { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount)) + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p)) goto bad; } } @@ -541,7 +585,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) { if (!isTiled(tif)) { - /* td_stripoffset might be NULL in an odd OJPEG case. See + /* td_stripoffset_p might be NULL in an odd OJPEG case. See * tif_dirread.c around line 3634. * XXX: OJPEG hack. * If a) compression is OJPEG, b) it's not a tiled TIFF, @@ -552,13 +596,13 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff) * We can get here when using tiffset on such a file. * See http://bugzilla.maptools.org/show_bug.cgi?id=2500 */ - if (tif->tif_dir.td_stripoffset != NULL && - !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) + if (tif->tif_dir.td_stripoffset_p != NULL && + !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p)) goto bad; } else { - if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) + if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p)) goto bad; } } @@ -946,15 +990,6 @@ bad: return(0); } -static float TIFFClampDoubleToFloat( double val ) -{ - if( val > FLT_MAX ) - return FLT_MAX; - if( val < -FLT_MAX ) - return -FLT_MAX; - return (float)val; -} - static int8 TIFFClampDoubleToInt8( double val ) { if( val > 127 ) @@ -1029,7 +1064,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di if (tif->tif_dir.td_bitspersample<=32) { for (i = 0; i < count; ++i) - ((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]); + ((float*)conv)[i] = _TIFFClampDoubleToFloat(value[i]); ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv); } else @@ -1661,22 +1696,52 @@ TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1 return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); } +static int _WriteAsType(TIFF* tif, uint64 strile_size, uint64 uncompressed_threshold) +{ + const uint16 compression = tif->tif_dir.td_compression; + if ( compression == COMPRESSION_NONE ) + { + return strile_size > uncompressed_threshold; + } + else if ( compression == COMPRESSION_JPEG || + compression == COMPRESSION_LZW || + compression == COMPRESSION_ADOBE_DEFLATE || + compression == COMPRESSION_LZMA || + compression == COMPRESSION_LERC || + compression == COMPRESSION_ZSTD || + compression == COMPRESSION_WEBP ) + { + /* For a few select compression types, we assume that in the worst */ + /* case the compressed size will be 10 times the uncompressed size */ + /* This is overly pessismistic ! */ + return strile_size >= uncompressed_threshold / 10; + } + return 1; +} + +static int WriteAsLong8(TIFF* tif, uint64 strile_size) +{ + return _WriteAsType(tif, strile_size, 0xFFFFFFFFU); +} + +static int WriteAsLong4(TIFF* tif, uint64 strile_size) +{ + return _WriteAsType(tif, strile_size, 0xFFFFU); +} + /************************************************************************/ /* TIFFWriteDirectoryTagLongLong8Array() */ /* */ -/* Write out LONG8 array as LONG8 for BigTIFF or LONG for */ -/* Classic TIFF with some checking. */ +/* Write out LONG8 array and write a SHORT/LONG/LONG8 depending */ +/* on strile size and Classic/BigTIFF mode. */ /************************************************************************/ static int TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) { static const char module[] = "TIFFWriteDirectoryTagLongLong8Array"; - uint64* ma; - uint32 mb; - uint32* p; - uint32* q; int o; + int write_aslong4; /* is this just a counting pass? */ if (dir==NULL) @@ -1685,37 +1750,105 @@ TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, return(1); } - /* We always write LONG8 for BigTIFF, no checking needed. */ - if( tif->tif_flags&TIFF_BIGTIFF ) - return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir, - tag,count,value); - - /* - ** For classic tiff we want to verify everything is in range for LONG - ** and convert to long format. - */ + if( tif->tif_dir.td_deferstrilearraywriting ) + { + return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL); + } - p = _TIFFmalloc(count*sizeof(uint32)); - if (p==NULL) + if( tif->tif_flags&TIFF_BIGTIFF ) { - TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); - return(0); + 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. */ + if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) + { + write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif)); + } + else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) + { + write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif)); + } + if( write_aslong8 ) + { + return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir, + tag,count,value); + } } - for (q=p, ma=value, mb=0; mb 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) { - if (*ma>0xFFFFFFFF) + write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif)); + } + else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) + { + write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif)); + } + if( write_aslong4 ) + { + /* + ** For classic tiff we want to verify everything is in range for LONG + ** and convert to long format. + */ + + uint32* p = _TIFFmalloc(count*sizeof(uint32)); + uint32* q; + uint64* ma; + uint32 mb; + + if (p==NULL) { - TIFFErrorExt(tif->tif_clientdata,module, - "Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file."); - _TIFFfree(p); + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return(0); } - *q= (uint32)(*ma); + + for (q=p, ma=value, mb=0; mb0xFFFFFFFF) + { + TIFFErrorExt(tif->tif_clientdata,module, + "Attempt to write value larger than 0xFFFFFFFF in LONG array."); + _TIFFfree(p); + return(0); + } + *q= (uint32)(*ma); + } + + o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); + _TIFFfree(p); } + else + { + uint16* p = _TIFFmalloc(count*sizeof(uint16)); + uint16* q; + uint64* ma; + uint32 mb; - o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); - _TIFFfree(p); + if (p==NULL) + { + TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); + return(0); + } + + for (q=p, ma=value, mb=0; mb0xFFFF) + { + /* Should not happen normally given the check we did before */ + TIFFErrorExt(tif->tif_clientdata,module, + "Attempt to write value larger than 0xFFFF in SHORT array."); + _TIFFfree(p); + return(0); + } + *q= (uint16)(*ma); + } + + o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,p); + _TIFFfree(p); + } return(o); } @@ -1893,12 +2026,14 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir n=3; if (n==3) { - if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) + if (tif->tif_dir.td_transferfunction[2] == NULL || + !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16))) n=2; } if (n==2) { - if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) + if (tif->tif_dir.td_transferfunction[1] == NULL || + !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16))) n=1; } if (n==0) @@ -2428,7 +2563,12 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag dir[m].tdir_count=count; dir[m].tdir_offset.toff_long8 = 0; if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) - _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); + { + if( data && datalength ) + { + _TIFFmemcpy(&dir[m].tdir_offset,data,datalength); + } + } else { uint64 na,nb; @@ -2820,13 +2960,60 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, TIFFSwabLong8( &entry_offset ); } +/* -------------------------------------------------------------------- */ +/* When a dummy tag was written due to TIFFDeferStrileArrayWriting() */ +/* -------------------------------------------------------------------- */ + if( entry_offset == 0 && entry_count == 0 && entry_type == 0 ) + { + if( tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS ) + { + entry_type = (tif->tif_flags&TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG; + } + else + { + int write_aslong8 = 1; + if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) + { + write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif)); + } + else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) + { + write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif)); + } + if( write_aslong8 ) + { + entry_type = TIFF_LONG8; + } + else + { + int write_aslong4 = 1; + if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS ) + { + write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif)); + } + else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS ) + { + write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif)); + } + if( write_aslong4 ) + { + entry_type = TIFF_LONG; + } + else + { + entry_type = TIFF_SHORT; + } + } + } + } + /* -------------------------------------------------------------------- */ /* What data type do we want to write this as? */ /* -------------------------------------------------------------------- */ if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) ) { if( in_datatype == TIFF_LONG8 ) - datatype = TIFF_LONG; + datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG; else if( in_datatype == TIFF_SLONG8 ) datatype = TIFF_SLONG; else if( in_datatype == TIFF_IFD8 ) @@ -2834,8 +3021,21 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, else datatype = in_datatype; } - else - datatype = in_datatype; + else + { + if( in_datatype == TIFF_LONG8 && + (entry_type == TIFF_SHORT || entry_type == TIFF_LONG || + entry_type == TIFF_LONG8 ) ) + datatype = entry_type; + else if( in_datatype == TIFF_SLONG8 && + (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8 ) ) + datatype = entry_type; + else if( in_datatype == TIFF_IFD8 && + (entry_type == TIFF_IFD || entry_type == TIFF_IFD8 ) ) + datatype = entry_type; + else + datatype = in_datatype; + } /* -------------------------------------------------------------------- */ /* Prepare buffer of actual data to write. This includes */ @@ -2884,6 +3084,29 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, } } } + else if( datatype == TIFF_SHORT && in_datatype == TIFF_LONG8 ) + { + tmsize_t i; + + for( i = 0; i < count; i++ ) + { + ((uint16 *) buf_to_write)[i] = + (uint16) ((uint64 *) data)[i]; + if( (uint64) ((uint16 *) buf_to_write)[i] != ((uint64 *) data)[i] ) + { + _TIFFfree( buf_to_write ); + TIFFErrorExt( tif->tif_clientdata, module, + "Value exceeds 16bit range of output type." ); + return 0; + } + } + } + else + { + TIFFErrorExt( tif->tif_clientdata, module, + "Unhandled type conversion." ); + return 0; + } if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) ) { @@ -2915,6 +3138,23 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, } } + if( (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) && + tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 ) + { + tif->tif_dir.td_stripoffset_entry.tdir_type = datatype; + tif->tif_dir.td_stripoffset_entry.tdir_count = count; + } + else if( (tag == TIFFTAG_TILEBYTECOUNTS || tag == TIFFTAG_STRIPBYTECOUNTS) && + tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 ) + { + tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype; + tif->tif_dir.td_stripbytecount_entry.tdir_count = count; + } + /* -------------------------------------------------------------------- */ /* If the tag type, and count match, then we just write it out */ /* over the old values without altering the directory entry at */ @@ -2966,6 +3206,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype, /* Adjust the directory entry. */ /* -------------------------------------------------------------------- */ entry_type = datatype; + entry_count = (uint64)count; memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) ); if (tif->tif_flags&TIFF_SWAB) TIFFSwabShort( (uint16 *) (direntry_raw + 2) ); diff --git a/src/3rdparty/libtiff/libtiff/tif_flush.c b/src/3rdparty/libtiff/libtiff/tif_flush.c index 881fac5..f7fa207 100644 --- a/src/3rdparty/libtiff/libtiff/tif_flush.c +++ b/src/3rdparty/libtiff/libtiff/tif_flush.c @@ -45,36 +45,8 @@ TIFFFlush(TIFF* tif) && !(tif->tif_flags & TIFF_DIRTYDIRECT) && tif->tif_mode == O_RDWR ) { - uint64 *offsets=NULL, *sizes=NULL; - - if( TIFFIsTiled(tif) ) - { - if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8, - tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8, - tif->tif_dir.td_nstrips, sizes ) ) - { - tif->tif_flags &= ~TIFF_DIRTYSTRIP; - tif->tif_flags &= ~TIFF_BEENWRITING; - return 1; - } - } - else - { - if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets ) - && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8, - tif->tif_dir.td_nstrips, offsets ) - && _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8, - tif->tif_dir.td_nstrips, sizes ) ) - { - tif->tif_flags &= ~TIFF_DIRTYSTRIP; - tif->tif_flags &= ~TIFF_BEENWRITING; - return 1; - } - } + if( TIFFForceStrileArrayWriting(tif) ) + return 1; } if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) @@ -84,6 +56,92 @@ TIFFFlush(TIFF* tif) return (1); } +/* + * This is an advanced writing function that must be used in a particular + * sequence, and together with TIFFDeferStrileArrayWriting(), + * to make its intended effect. Its aim is to force the writing of + * the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when + * they have not yet been rewritten. + * + * The typical sequence of calls is: + * TIFFOpen() + * [ TIFFCreateDirectory(tif) ] + * Set fields with calls to TIFFSetField(tif, ...) + * TIFFDeferStrileArrayWriting(tif) + * TIFFWriteCheck(tif, ...) + * TIFFWriteDirectory(tif) + * ... potentially create other directories and come back to the above directory + * TIFFForceStrileArrayWriting(tif) + * + * Returns 1 in case of success, 0 otherwise. + */ +int TIFFForceStrileArrayWriting(TIFF* tif) +{ + static const char module[] = "TIFFForceStrileArrayWriting"; + const int isTiled = TIFFIsTiled(tif); + + if (tif->tif_mode == O_RDONLY) + { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, + "File opened in read-only mode"); + return 0; + } + if( tif->tif_diroff == 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory has not yet been written"); + return 0; + } + if( (tif->tif_flags & TIFF_DIRTYDIRECT) != 0 ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Directory has changes other than the strile arrays. " + "TIFFRewriteDirectory() should be called instead"); + return 0; + } + + if( !(tif->tif_flags & TIFF_DIRTYSTRIP) ) + { + if( !(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && + tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0) ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Function not called together with " + "TIFFDeferStrileArrayWriting()"); + return 0; + } + + if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) + return 0; + } + + if( _TIFFRewriteField( tif, + isTiled ? TIFFTAG_TILEOFFSETS : + TIFFTAG_STRIPOFFSETS, + TIFF_LONG8, + tif->tif_dir.td_nstrips, + tif->tif_dir.td_stripoffset_p ) + && _TIFFRewriteField( tif, + isTiled ? TIFFTAG_TILEBYTECOUNTS : + TIFFTAG_STRIPBYTECOUNTS, + TIFF_LONG8, + tif->tif_dir.td_nstrips, + tif->tif_dir.td_stripbytecount_p ) ) + { + tif->tif_flags &= ~TIFF_DIRTYSTRIP; + tif->tif_flags &= ~TIFF_BEENWRITING; + return 1; + } + + return 0; +} + /* * Flush buffered data to the file. * diff --git a/src/3rdparty/libtiff/libtiff/tif_getimage.c b/src/3rdparty/libtiff/libtiff/tif_getimage.c index a389ffb..4da785d 100644 --- a/src/3rdparty/libtiff/libtiff/tif_getimage.c +++ b/src/3rdparty/libtiff/libtiff/tif_getimage.c @@ -2969,7 +2969,7 @@ TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop if( !TIFFIsTiled( tif ) ) { TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), - "Can't use TIFFReadRGBATile() with stripped file."); + "Can't use TIFFReadRGBATile() with striped file."); return (0); } diff --git a/src/3rdparty/libtiff/libtiff/tif_jpeg.c b/src/3rdparty/libtiff/libtiff/tif_jpeg.c index f2ddc33..93ae2ea 100644 --- a/src/3rdparty/libtiff/libtiff/tif_jpeg.c +++ b/src/3rdparty/libtiff/libtiff/tif_jpeg.c @@ -780,12 +780,9 @@ JPEGFixupTagsSubsampling(TIFF* tif) */ static const char module[] = "JPEGFixupTagsSubsampling"; struct JPEGFixupTagsSubsamplingData m; + uint64 fileoffset = TIFFGetStrileOffset(tif, 0); - _TIFFFillStriles( tif ); - - if( tif->tif_dir.td_stripbytecount == NULL - || tif->tif_dir.td_stripoffset == NULL - || tif->tif_dir.td_stripbytecount[0] == 0 ) + if( fileoffset == 0 ) { /* Do not even try to check if the first strip/tile does not yet exist, as occurs when GDAL has created a new NULL file @@ -804,9 +801,9 @@ JPEGFixupTagsSubsampling(TIFF* tif) } m.buffercurrentbyte=NULL; m.bufferbytesleft=0; - m.fileoffset=tif->tif_dir.td_stripoffset[0]; + m.fileoffset=fileoffset; m.filepositioned=0; - m.filebytesleft=tif->tif_dir.td_stripbytecount[0]; + m.filebytesleft=TIFFGetStrileByteCount(tif, 0); if (!JPEGFixupTagsSubsamplingSec(&m)) TIFFWarningExt(tif->tif_clientdata,module, "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped"); @@ -1566,7 +1563,7 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset; #else JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; - if (cc < (tmsize_t) (clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp)) { + if (cc < (tmsize_t)(clumpoffset + (tmsize_t)samples_per_clump*(clumps_per_line-1) + hsamp)) { TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw", "application buffer not large enough for all data, possible subsampling issue"); return 0; @@ -2126,8 +2123,8 @@ JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) /* data is expected to be supplied in multiples of a clumpline */ /* a clumpline is equivalent to v_sampling desubsampled scanlines */ /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */ - bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) - *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) + bytesperclumpline = ((((tmsize_t)sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling) + *((tmsize_t)sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7) /8; nrows = ( cc / bytesperclumpline ) * sp->v_sampling; diff --git a/src/3rdparty/libtiff/libtiff/tif_luv.c b/src/3rdparty/libtiff/libtiff/tif_luv.c index 46d2dff..6fe4858 100644 --- a/src/3rdparty/libtiff/libtiff/tif_luv.c +++ b/src/3rdparty/libtiff/libtiff/tif_luv.c @@ -742,9 +742,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) #undef exp2 /* Conflict with C'99 function */ #define exp2(x) exp(M_LN2*(x)) -#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ - (int)(x) : \ - (int)((x) + rand()*(1./RAND_MAX) - .5)) +static int itrunc(double x, int m) +{ + if( m == SGILOGENCODE_NODITHER ) + return (int)x; + /* Silence CoverityScan warning about bad crypto function */ + /* coverity[dont_call] */ + return (int)(x + rand()*(1./RAND_MAX) - .5); +} #if !LOGLUV_PUBLIC static @@ -1501,7 +1506,7 @@ LogLuvSetupEncode(TIFF* tif) switch (td->td_photometric) { case PHOTOMETRIC_LOGLUV: if (!LogLuvInitState(tif)) - break; + return (0); if (td->td_compression == COMPRESSION_SGILOG24) { tif->tif_encoderow = LogLuvEncode24; switch (sp->user_datafmt) { @@ -1534,7 +1539,7 @@ LogLuvSetupEncode(TIFF* tif) break; case PHOTOMETRIC_LOGL: if (!LogL16InitState(tif)) - break; + return (0); tif->tif_encoderow = LogL16Encode; switch (sp->user_datafmt) { case SGILOGDATAFMT_FLOAT: @@ -1550,7 +1555,7 @@ LogLuvSetupEncode(TIFF* tif) TIFFErrorExt(tif->tif_clientdata, module, "Inappropriate photometric interpretation %d for SGILog compression; %s", td->td_photometric, "must be either LogLUV or LogL"); - break; + return (0); } sp->encoder_state = 1; return (1); diff --git a/src/3rdparty/libtiff/libtiff/tif_lzw.c b/src/3rdparty/libtiff/libtiff/tif_lzw.c index ac685dd..21064f2 100644 --- a/src/3rdparty/libtiff/libtiff/tif_lzw.c +++ b/src/3rdparty/libtiff/libtiff/tif_lzw.c @@ -247,6 +247,8 @@ LZWSetupDecode(TIFF* tif) /* * Zero-out the unused entries */ + /* Silence false positive */ + /* coverity[overrun-buffer-arg] */ _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, (CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); } diff --git a/src/3rdparty/libtiff/libtiff/tif_ojpeg.c b/src/3rdparty/libtiff/libtiff/tif_ojpeg.c index 27385d8..bf0d1a2 100644 --- a/src/3rdparty/libtiff/libtiff/tif_ojpeg.c +++ b/src/3rdparty/libtiff/libtiff/tif_ojpeg.c @@ -243,6 +243,7 @@ typedef enum { typedef struct { TIFF* tif; int decoder_ok; + int error_in_raw_data_decoding; #ifndef LIBJPEG_ENCAP_EXTERNAL JMP_BUF exit_jmpbuf; #endif @@ -678,7 +679,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s) if (OJPEGReadSecondarySos(tif,s)==0) return(0); } - if isTiled(tif) + if (isTiled(tif)) m=tif->tif_curtile; else m=tif->tif_curstrip; @@ -742,6 +743,7 @@ OJPEGPreDecodeSkipRaw(TIFF* tif) } m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; sp->subsampling_convert_state=0; + sp->error_in_raw_data_decoding=0; } while (m>=sp->subsampling_convert_clines) { @@ -792,6 +794,10 @@ OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s) TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized"); return 0; } + if( sp->error_in_raw_data_decoding ) + { + return 0; + } if (sp->libjpeg_jpeg_query_style==0) { if (OJPEGDecodeRaw(tif,buf,cc)==0) @@ -831,8 +837,41 @@ OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc) { if (sp->subsampling_convert_state==0) { + const jpeg_decompress_struct* cinfo = &sp->libjpeg_jpeg_decompress_struct; + int width = 0; + int last_col_width = 0; + int jpeg_bytes; + int expected_bytes; + int i; + if (cinfo->MCUs_per_row == 0) + { + sp->error_in_raw_data_decoding = 1; + return 0; + } + for (i = 0; i < cinfo->comps_in_scan; ++i) + { + const jpeg_component_info* info = cinfo->cur_comp_info[i]; +#if JPEG_LIB_VERSION >= 70 + width += info->MCU_width * info->DCT_h_scaled_size; + last_col_width += info->last_col_width * info->DCT_h_scaled_size; +#else + width += info->MCU_width * info->DCT_scaled_size; + last_col_width += info->last_col_width * info->DCT_scaled_size; +#endif + } + jpeg_bytes = (cinfo->MCUs_per_row - 1) * width + last_col_width; + expected_bytes = sp->subsampling_convert_clinelenout * sp->subsampling_ver * sp->subsampling_hor; + if (jpeg_bytes != expected_bytes) + { + TIFFErrorExt(tif->tif_clientdata,module,"Inconsistent number of MCU in codestream"); + sp->error_in_raw_data_decoding = 1; + return(0); + } if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0) + { + sp->error_in_raw_data_decoding = 1; return(0); + } } oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen; ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen; @@ -990,7 +1029,6 @@ OJPEGSubsamplingCorrect(TIFF* tif) OJPEGState* sp=(OJPEGState*)tif->tif_data; uint8 mh; uint8 mv; - _TIFFFillStriles( tif ); assert(sp->subsamplingcorrect_done==0); if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && @@ -1046,7 +1084,7 @@ OJPEGReadHeaderInfo(TIFF* tif) assert(sp->readheader_done==0); sp->image_width=tif->tif_dir.td_imagewidth; sp->image_length=tif->tif_dir.td_imagelength; - if isTiled(tif) + if (isTiled(tif)) { sp->strile_width=tif->tif_dir.td_tilewidth; sp->strile_length=tif->tif_dir.td_tilelength; @@ -1082,6 +1120,12 @@ OJPEGReadHeaderInfo(TIFF* tif) } if (sp->strile_lengthimage_length) { + if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) || + ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4))) + { + TIFFErrorExt(tif->tif_clientdata,module,"Invalid subsampling values"); + return(0); + } if (sp->strile_length%(sp->subsampling_ver*8)!=0) { TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); @@ -1197,7 +1241,13 @@ OJPEGWriteHeaderInfo(TIFF* tif) sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines; sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen; - sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen); + /* The calloc is not normally necessary, except in some edge/broken cases */ + /* for example for a tiled image of height 1 with a tile height of 1 and subsampling_hor=subsampling_ver=2 */ + /* In that case, libjpeg will only fill the 8 first lines of the 16 lines */ + /* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 */ + /* Even if this case is allowed (?), its handling is broken because OJPEGPreDecode() should also likely */ + /* reset subsampling_convert_state to 0 when changing tile. */ + sp->subsampling_convert_ycbcrbuf=_TIFFcalloc(1, sp->subsampling_convert_ycbcrbuflen); if (sp->subsampling_convert_ycbcrbuf==0) { TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); @@ -1223,10 +1273,11 @@ OJPEGWriteHeaderInfo(TIFF* tif) *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen; for (n=0; nsubsampling_convert_clines; n++) *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; - sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor); + sp->subsampling_convert_clinelenout=sp->strile_width/sp->subsampling_hor + ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0); sp->subsampling_convert_state=0; + sp->error_in_raw_data_decoding=0; sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2); - sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver); + sp->lines_per_strile=sp->strile_length/sp->subsampling_ver + ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0); sp->subsampling_convert_log=1; } } @@ -1272,7 +1323,9 @@ OJPEGReadHeaderInfoSec(TIFF* tif) } else { - if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) + if ((sp->jpeg_interchange_format_length==0) || + (sp->jpeg_interchange_format > TIFF_UINT64_MAX - sp->jpeg_interchange_format_length) || + (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size)) sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format; } } @@ -1989,32 +2042,30 @@ OJPEGReadBufferFill(OJPEGState* sp) sp->in_buffer_source=osibsStrile; break; case osibsStrile: - if (!_TIFFFillStriles( sp->tif ) - || sp->tif->tif_dir.td_stripoffset == NULL - || sp->tif->tif_dir.td_stripbytecount == NULL) - return 0; - if (sp->in_buffer_next_strile==sp->in_buffer_strile_count) sp->in_buffer_source=osibsEof; else { - sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile]; + int err = 0; + sp->in_buffer_file_pos=TIFFGetStrileOffsetWithErr(sp->tif, sp->in_buffer_next_strile, &err); + if( err ) + return 0; if (sp->in_buffer_file_pos!=0) { + uint64 bytecount = TIFFGetStrileByteCountWithErr(sp->tif, sp->in_buffer_next_strile, &err); + if( err ) + return 0; if (sp->in_buffer_file_pos>=sp->file_size) sp->in_buffer_file_pos=0; - else if (sp->tif->tif_dir.td_stripbytecount==NULL) + else if (bytecount==0) sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; else { - if (sp->tif->tif_dir.td_stripbytecount == 0) { - TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing"); - return(0); - } - sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile]; + sp->in_buffer_file_togo=bytecount; if (sp->in_buffer_file_togo==0) sp->in_buffer_file_pos=0; - else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) + else if (sp->in_buffer_file_pos > TIFF_UINT64_MAX - sp->in_buffer_file_togo || + sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size) sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos; } } diff --git a/src/3rdparty/libtiff/libtiff/tif_open.c b/src/3rdparty/libtiff/libtiff/tif_open.c index c574c45..3cb53d4 100644 --- a/src/3rdparty/libtiff/libtiff/tif_open.c +++ b/src/3rdparty/libtiff/libtiff/tif_open.c @@ -131,6 +131,7 @@ TIFFClientOpen( if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { TIFFErrorExt(clientdata, module, "One of the client procedures is NULL pointer."); + _TIFFfree(tif); goto bad2; } tif->tif_readproc = readproc; @@ -181,6 +182,8 @@ TIFFClientOpen( * 'h' read TIFF header only, do not load the first IFD * '4' ClassicTIFF for creating a file (default) * '8' BigTIFF for creating a file + * 'D' enable use of deferred strip/tile offset/bytecount array loading. + * 'O' on-demand loading of values instead of whole array loading (implies D) * * The use of the 'l' and 'b' flags is strongly discouraged. * These flags are provided solely because numerous vendors, @@ -262,7 +265,22 @@ TIFFClientOpen( if (m&O_CREAT) tif->tif_flags |= TIFF_BIGTIFF; break; + case 'D': + tif->tif_flags |= TIFF_DEFERSTRILELOAD; + break; + case 'O': + if( m == O_RDONLY ) + tif->tif_flags |= (TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD); + break; } + +#ifdef DEFER_STRILE_LOAD + /* Compatibility with old DEFER_STRILE_LOAD compilation flag */ + /* Probably unneeded, since to the best of my knowledge (E. Rouault) */ + /* GDAL was the only user of this, and will now use the new 'D' flag */ + tif->tif_flags |= TIFF_DEFERSTRILELOAD; +#endif + /* * Read in TIFF header. */ diff --git a/src/3rdparty/libtiff/libtiff/tif_pixarlog.c b/src/3rdparty/libtiff/libtiff/tif_pixarlog.c index 12c2372..6264090 100644 --- a/src/3rdparty/libtiff/libtiff/tif_pixarlog.c +++ b/src/3rdparty/libtiff/libtiff/tif_pixarlog.c @@ -637,12 +637,13 @@ PixarLogGuessDataFmt(TIFFDirectory *td) static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2) { - return _TIFFMultiplySSize(NULL, m1, m2, NULL); + return _TIFFMultiplySSize(NULL, m1, m2, NULL); } static tmsize_t add_ms(tmsize_t m1, tmsize_t m2) { + assert(m1 >= 0 && m2 >= 0); /* if either input is zero, assume overflow already occurred */ if (m1 == 0 || m2 == 0) return 0; @@ -812,9 +813,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) TIFFErrorExt(tif->tif_clientdata, module, "Decoding error at scanline %lu, %s", (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); - if (inflateSync(&sp->stream) != Z_OK) - return (0); - continue; + return (0); } if (state != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", @@ -1148,7 +1147,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) llen = sp->stride * td->td_imagewidth; /* Check against the number of elements (of size uint16) of sp->tbuf */ - if( n > (tmsize_t)(td->td_rowsperstrip * llen) ) + if( n > ((tmsize_t)td->td_rowsperstrip * llen) ) { TIFFErrorExt(tif->tif_clientdata, module, "Too many input bytes provided"); diff --git a/src/3rdparty/libtiff/libtiff/tif_print.c b/src/3rdparty/libtiff/libtiff/tif_print.c index 1d86adb..a073794 100644 --- a/src/3rdparty/libtiff/libtiff/tif_print.c +++ b/src/3rdparty/libtiff/libtiff/tif_print.c @@ -652,8 +652,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) if (tif->tif_tagmethods.printdir) (*tif->tif_tagmethods.printdir)(tif, fd, flags); - _TIFFFillStriles( tif ); - if ((flags & TIFFPRINT_STRIPS) && TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { uint32 s; @@ -665,13 +663,13 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", (unsigned long) s, - td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0, - td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0); + (unsigned __int64) TIFFGetStrileOffset(tif, s), + (unsigned __int64) TIFFGetStrileByteCount(tif, s)); #else fprintf(fd, " %3lu: [%8llu, %8llu]\n", (unsigned long) s, - td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0, - td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0); + (unsigned long long) TIFFGetStrileOffset(tif, s), + (unsigned long long) TIFFGetStrileByteCount(tif, s)); #endif } } diff --git a/src/3rdparty/libtiff/libtiff/tif_read.c b/src/3rdparty/libtiff/libtiff/tif_read.c index aa31054..527fadd 100644 --- a/src/3rdparty/libtiff/libtiff/tif_read.c +++ b/src/3rdparty/libtiff/libtiff/tif_read.c @@ -60,6 +60,22 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, #endif tmsize_t already_read = 0; + +#if SIZEOF_SIZE_T != 8 + /* On 32 bit processes, if the request is large enough, check against */ + /* file size */ + if( size > 1000 * 1000 * 1000 ) + { + uint64 filesize = TIFFGetFileSize(tif); + if( (uint64)size >= filesize ) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Chunk size requested is larger than file size."); + return 0; + } + } +#endif + /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ /* so as to avoid allocating too much memory in case the file is too */ /* short. We could ask for the file size, but this might be */ @@ -102,6 +118,11 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, } tif->tif_rawdata = new_rawdata; } + if( tif->tif_rawdata == NULL ) + { + /* should not happen in practice but helps CoverityScan */ + return 0; + } bytes_read = TIFFReadFile(tif, tif->tif_rawdata + rawdata_offset + already_read, to_read); @@ -169,17 +190,14 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) tmsize_t to_read; tmsize_t read_ahead_mod; /* tmsize_t bytecountm; */ - - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - + /* * Expand raw data buffer, if needed, to hold data * strip coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ - /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ + /* bytecountm=(tmsize_t) TIFFGetStrileByteCount(tif, strip); */ /* Not completely sure where the * 2 comes from, but probably for */ /* an exponentional growth strategy of tif_rawdatasize */ @@ -223,7 +241,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) /* ** Seek to the point in the file where more data should be read. */ - read_offset = td->td_stripoffset[strip] + read_offset = TIFFGetStrileOffset(tif, strip) + tif->tif_rawdataoff + tif->tif_rawdataloaded; if (!SeekOK(tif, read_offset)) { @@ -240,10 +258,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) to_read = read_ahead_mod - unused_data; else to_read = tif->tif_rawdatasize - unused_data; - if( (uint64) to_read > td->td_stripbytecount[strip] + if( (uint64) to_read > TIFFGetStrileByteCount(tif, strip) - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { - to_read = (tmsize_t) td->td_stripbytecount[strip] + to_read = (tmsize_t) TIFFGetStrileByteCount(tif, strip) - tif->tif_rawdataoff - tif->tif_rawdataloaded; } @@ -282,7 +300,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) /* For JPEG, if there are multiple scans (can generally be known */ /* with the read_ahead used), we need to read the whole strip */ if( tif->tif_dir.td_compression==COMPRESSION_JPEG && - (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] ) + (uint64)tif->tif_rawcc < TIFFGetStrileByteCount(tif, strip) ) { if( TIFFJPEGIsFullStripRequired(tif) ) { @@ -341,9 +359,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) * read it a few lines at a time? */ #if defined(CHUNKY_STRIP_READ_SUPPORT) - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10 + whole_strip = TIFFGetStrileByteCount(tif, strip) < 10 || isMapped(tif); if( td->td_compression == COMPRESSION_LERC || td->td_compression == COMPRESSION_JBIG ) @@ -396,7 +412,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample ) else if( !whole_strip ) { if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead - && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < td->td_stripbytecount[strip] ) + && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < TIFFGetStrileByteCount(tif, strip) ) { if( !TIFFFillStripPartial(tif,strip,read_ahead,0) ) return 0; @@ -593,16 +609,11 @@ static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, const char* module) { - TIFFDirectory *td = &tif->tif_dir; - - if (!_TIFFFillStriles( tif )) - return ((tmsize_t)(-1)); - assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tmsize_t cc; - if (!SeekOK(tif, td->td_stripoffset[strip])) { + if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip))) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); @@ -628,8 +639,8 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, } else { tmsize_t ma = 0; tmsize_t n; - if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| - ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) + if ((TIFFGetStrileOffset(tif, strip) > (uint64)TIFF_TMSIZE_T_MAX)|| + ((ma=(tmsize_t)TIFFGetStrileOffset(tif, strip))>tif->tif_size)) { n=0; } @@ -673,12 +684,10 @@ static tmsize_t TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, tmsize_t size, const char* module) { - TIFFDirectory *td = &tif->tif_dir; - assert( !isMapped(tif) ); assert((tif->tif_flags&TIFF_NOREADRAW)==0); - if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) { + if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip_or_tile))) { if( is_strip ) { TIFFErrorExt(tif->tif_clientdata, module, @@ -714,7 +723,7 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) { static const char module[] = "TIFFReadRawStrip"; TIFFDirectory *td = &tif->tif_dir; - uint64 bytecount; + uint64 bytecount64; tmsize_t bytecountm; if (!TIFFCheckRead(tif, 0)) @@ -732,16 +741,23 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size) "Compression scheme does not support access to raw uncompressed data"); return ((tmsize_t)(-1)); } - bytecount = td->td_stripbytecount[strip]; - bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount, module); - if (bytecountm == 0) { + bytecount64 = TIFFGetStrileByteCount(tif, strip); + if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64) + bytecountm = size; + else + bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module); + if( bytecountm == 0 ) { return ((tmsize_t)(-1)); } - if (size != (tmsize_t)(-1) && size < bytecountm) - bytecountm = size; return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module)); } +TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW +static uint64 NoSantizeSubUInt64(uint64 a, uint64 b) +{ + return a - b; +} + /* * Read the specified strip and setup for decoding. The data buffer is * expanded, as necessary, to hold the strip's data. @@ -752,12 +768,9 @@ TIFFFillStrip(TIFF* tif, uint32 strip) static const char module[] = "TIFFFillStrip"; TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - if ((tif->tif_flags&TIFF_NOREADRAW)==0) { - uint64 bytecount = td->td_stripbytecount[strip]; + uint64 bytecount = TIFFGetStrileByteCount(tif, strip); if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, @@ -810,13 +823,13 @@ TIFFFillStrip(TIFF* tif, uint32 strip) * We must check for overflow, potentially causing * an OOB read. Instead of simple * - * td->td_stripoffset[strip]+bytecount > tif->tif_size + * TIFFGetStrileOffset(tif, strip)+bytecount > tif->tif_size * * comparison (which can overflow) we do the following * two comparisons: */ if (bytecount > (uint64)tif->tif_size || - td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) { + TIFFGetStrileOffset(tif, strip) > (uint64)tif->tif_size - bytecount) { /* * This error message might seem strange, but * it's what would happen if a read were done @@ -828,7 +841,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip) "Read error on strip %lu; " "got %I64u bytes, expected %I64u", (unsigned long) strip, - (unsigned __int64) tif->tif_size - td->td_stripoffset[strip], + (unsigned __int64) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)), (unsigned __int64) bytecount); #else TIFFErrorExt(tif->tif_clientdata, module, @@ -836,7 +849,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip) "Read error on strip %lu; " "got %llu bytes, expected %llu", (unsigned long) strip, - (unsigned long long) tif->tif_size - td->td_stripoffset[strip], + (unsigned long long) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)), (unsigned long long) bytecount); #endif tif->tif_curstrip = NOSTRIP; @@ -865,7 +878,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip) } tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_rawdatasize = (tmsize_t)bytecount; - tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip]; + tif->tif_rawdata = tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, strip); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; @@ -1080,16 +1093,11 @@ _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile, static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { - TIFFDirectory *td = &tif->tif_dir; - - if (!_TIFFFillStriles( tif )) - return ((tmsize_t)(-1)); - assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tmsize_t cc; - if (!SeekOK(tif, td->td_stripoffset[tile])) { + if (!SeekOK(tif, TIFFGetStrileOffset(tif, tile))) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at row %lu, col %lu, tile %lu", (unsigned long) tif->tif_row, @@ -1119,9 +1127,9 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m } else { tmsize_t ma,mb; tmsize_t n; - ma=(tmsize_t)td->td_stripoffset[tile]; + ma=(tmsize_t)TIFFGetStrileOffset(tif, tile); mb=ma+size; - if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) + if ((TIFFGetStrileOffset(tif, tile) > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size)) n=0; else if ((mbtif->tif_size)) n=tif->tif_size-ma; @@ -1177,11 +1185,12 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size) "Compression scheme does not support access to raw uncompressed data"); return ((tmsize_t)(-1)); } - bytecount64 = td->td_stripbytecount[tile]; - if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) - bytecount64 = (uint64)size; - bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module); - if( bytecountm == 0 ) { + bytecount64 = TIFFGetStrileByteCount(tif, tile); + if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64) + bytecountm = size; + else + bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module); + if( bytecountm == 0 ) { return ((tmsize_t)(-1)); } return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); @@ -1197,12 +1206,9 @@ TIFFFillTile(TIFF* tif, uint32 tile) static const char module[] = "TIFFFillTile"; TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - if ((tif->tif_flags&TIFF_NOREADRAW)==0) { - uint64 bytecount = td->td_stripbytecount[tile]; + uint64 bytecount = TIFFGetStrileByteCount(tif, tile); if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, @@ -1255,13 +1261,13 @@ TIFFFillTile(TIFF* tif, uint32 tile) * We must check for overflow, potentially causing * an OOB read. Instead of simple * - * td->td_stripoffset[tile]+bytecount > tif->tif_size + * TIFFGetStrileOffset(tif, tile)+bytecount > tif->tif_size * * comparison (which can overflow) we do the following * two comparisons: */ if (bytecount > (uint64)tif->tif_size || - td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) { + TIFFGetStrileOffset(tif, tile) > (uint64)tif->tif_size - bytecount) { tif->tif_curtile = NOTILE; return (0); } @@ -1290,7 +1296,7 @@ TIFFFillTile(TIFF* tif, uint32 tile) tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdata = - tif->tif_base + (tmsize_t)td->td_stripoffset[tile]; + tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, tile); tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_flags |= TIFF_BUFFERMMAP; @@ -1349,7 +1355,8 @@ TIFFFillTile(TIFF* tif, uint32 tile) tif->tif_rawdataoff = 0; tif->tif_rawdataloaded = bytecountm; - if (!isFillOrder(tif, td->td_fillorder) && + if (tif->tif_rawdata != NULL && + !isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) TIFFReverseBits(tif->tif_rawdata, tif->tif_rawdataloaded); @@ -1416,9 +1423,6 @@ TIFFStartStrip(TIFF* tif, uint32 strip) { TIFFDirectory *td = &tif->tif_dir; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupdecode)(tif)) return (0); @@ -1439,7 +1443,7 @@ TIFFStartStrip(TIFF* tif, uint32 strip) if( tif->tif_rawdataloaded > 0 ) tif->tif_rawcc = tif->tif_rawdataloaded; else - tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; + tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, strip); } return ((*tif->tif_predecode)(tif, (uint16)(strip / td->td_stripsperimage))); @@ -1456,9 +1460,6 @@ TIFFStartTile(TIFF* tif, uint32 tile) TIFFDirectory *td = &tif->tif_dir; uint32 howmany32; - if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) - return 0; - if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if (!(*tif->tif_setupdecode)(tif)) return (0); @@ -1489,7 +1490,7 @@ TIFFStartTile(TIFF* tif, uint32 tile) if( tif->tif_rawdataloaded > 0 ) tif->tif_rawcc = tif->tif_rawdataloaded; else - tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; + tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, tile); } return ((*tif->tif_predecode)(tif, (uint16)(tile/td->td_stripsperimage))); @@ -1504,13 +1505,100 @@ TIFFCheckRead(TIFF* tif, int tiles) } if (tiles ^ isTiled(tif)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? - "Can not read tiles from a stripped image" : + "Can not read tiles from a striped image" : "Can not read scanlines from a tiled image"); return (0); } return (1); } +/* Use the provided input buffer (inbuf, insize) and decompress it into + * (outbuf, outsize). + * This function replaces the use of TIFFReadEncodedStrip()/TIFFReadEncodedTile() + * when the user can provide the buffer for the input data, for example when + * he wants to avoid libtiff to read the strile offset/count values from the + * [Strip|Tile][Offsets/ByteCounts] array. + * inbuf content must be writable (if bit reversal is needed) + * Returns 1 in case of success, 0 otherwise. + */ +int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile, + void* inbuf, tmsize_t insize, + void* outbuf, tmsize_t outsize) +{ + static const char module[] = "TIFFReadFromUserBuffer"; + TIFFDirectory *td = &tif->tif_dir; + int ret = 1; + uint32 old_tif_flags = tif->tif_flags; + tmsize_t old_rawdatasize = tif->tif_rawdatasize; + void* old_rawdata = tif->tif_rawdata; + + if (tif->tif_mode == O_WRONLY) { + TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading"); + return 0; + } + if (tif->tif_flags&TIFF_NOREADRAW) + { + TIFFErrorExt(tif->tif_clientdata, module, + "Compression scheme does not support access to raw uncompressed data"); + return 0; + } + + tif->tif_flags &= ~TIFF_MYBUFFER; + tif->tif_flags |= TIFF_BUFFERMMAP; + tif->tif_rawdatasize = insize; + tif->tif_rawdata = inbuf; + tif->tif_rawdataoff = 0; + tif->tif_rawdataloaded = insize; + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + { + TIFFReverseBits(inbuf, insize); + } + + if( TIFFIsTiled(tif) ) + { + if( !TIFFStartTile(tif, strile) || + !(*tif->tif_decodetile)(tif, (uint8*) outbuf, outsize, + (uint16)(strile/td->td_stripsperimage)) ) + { + ret = 0; + } + } + else + { + uint32 rowsperstrip=td->td_rowsperstrip; + uint32 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*) outbuf, outsize, + (uint16)(strile/stripsperplane)) ) + { + ret = 0; + } + } + if( ret ) + { + (*tif->tif_postdecode)(tif, (uint8*) outbuf, outsize); + } + + if (!isFillOrder(tif, td->td_fillorder) && + (tif->tif_flags & TIFF_NOBITREV) == 0) + { + TIFFReverseBits(inbuf, insize); + } + + tif->tif_flags = old_tif_flags; + tif->tif_rawdatasize = old_rawdatasize; + tif->tif_rawdata = old_rawdata; + tif->tif_rawdataoff = 0; + tif->tif_rawdataloaded = 0; + + return ret; +} + void _TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc) { diff --git a/src/3rdparty/libtiff/libtiff/tif_strip.c b/src/3rdparty/libtiff/libtiff/tif_strip.c index 2366acf..c08c60a 100644 --- a/src/3rdparty/libtiff/libtiff/tif_strip.c +++ b/src/3rdparty/libtiff/libtiff/tif_strip.c @@ -140,8 +140,7 @@ uint64 TIFFRawStripSize64(TIFF* tif, uint32 strip) { static const char module[] = "TIFFRawStripSize64"; - TIFFDirectory* td = &tif->tif_dir; - uint64 bytecount = td->td_stripbytecount[strip]; + uint64 bytecount = TIFFGetStrileByteCount(tif, strip); if (bytecount == 0) { diff --git a/src/3rdparty/libtiff/libtiff/tif_thunder.c b/src/3rdparty/libtiff/libtiff/tif_thunder.c index 2388dbb..db6383a 100644 --- a/src/3rdparty/libtiff/libtiff/tif_thunder.c +++ b/src/3rdparty/libtiff/libtiff/tif_thunder.c @@ -122,17 +122,17 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels) break; case THUNDER_2BITDELTAS: /* 2-bit deltas */ if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); + SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); + SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); if ((delta = (n & 3)) != DELTA2_SKIP) - SETPIXEL(op, lastpixel + twobitdeltas[delta]); + SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta])); break; case THUNDER_3BITDELTAS: /* 3-bit deltas */ if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) - SETPIXEL(op, lastpixel + threebitdeltas[delta]); + SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta])); if ((delta = (n & 7)) != DELTA3_SKIP) - SETPIXEL(op, lastpixel + threebitdeltas[delta]); + SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta])); break; case THUNDER_RAW: /* raw data */ SETPIXEL(op, n); diff --git a/src/3rdparty/libtiff/libtiff/tif_write.c b/src/3rdparty/libtiff/libtiff/tif_write.c index a31ecd1..33e803c 100644 --- a/src/3rdparty/libtiff/libtiff/tif_write.c +++ b/src/3rdparty/libtiff/libtiff/tif_write.c @@ -128,10 +128,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) tif->tif_rawcc = 0; tif->tif_rawcp = tif->tif_rawdata; - if( td->td_stripbytecount[strip] > 0 ) + if( td->td_stripbytecount_p[strip] > 0 ) { /* if we are writing over existing tiles, zero length */ - td->td_stripbytecount[strip] = 0; + td->td_stripbytecount_p[strip] = 0; /* this forces TIFFAppendToStrip() to do a seek */ tif->tif_curoff = 0; @@ -176,6 +176,32 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample) return (status); } +/* Make sure that at the first attempt of rewriting a tile/strip, we will have */ +/* more bytes available in the output buffer than the previous byte count, */ +/* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ +/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ +static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32 strip_or_tile) +{ + TIFFDirectory *td = &tif->tif_dir; + if( td->td_stripbytecount_p[strip_or_tile] > 0 ) + { + /* The +1 is to ensure at least one extra bytes */ + /* The +4 is because the LZW encoder flushes 4 bytes before the limit */ + uint64 safe_buffer_size = (uint64)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4); + if( tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size ) + { + if( !(TIFFWriteBufferSetup(tif, NULL, + (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))) ) + return 0; + } + + /* Force TIFFAppendToStrip() to consider placing data at end + of file. */ + tif->tif_curoff = 0; + } + return 1; +} + /* * Encode the supplied data and write it to the * specified strip. @@ -222,6 +248,13 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curstrip = strip; + if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) { + return ((tmsize_t)(-1)); + } + + tif->tif_rawcc = 0; + tif->tif_rawcp = tif->tif_rawdata; + if (td->td_stripsperimage == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); return ((tmsize_t) -1); @@ -234,27 +267,6 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc) tif->tif_flags |= TIFF_CODERSETUP; } - if( td->td_stripbytecount[strip] > 0 ) - { - /* Make sure that at the first attempt of rewriting the tile, we will have */ - /* more bytes available in the output buffer than the previous byte count, */ - /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ - /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ - if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] ) - { - if( !(TIFFWriteBufferSetup(tif, NULL, - (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) ) - return ((tmsize_t)(-1)); - } - - /* Force TIFFAppendToStrip() to consider placing data at end - of file. */ - tif->tif_curoff = 0; - } - - tif->tif_rawcc = 0; - tif->tif_rawcp = tif->tif_rawdata; - tif->tif_flags &= ~TIFF_POSTENCODE; /* shortcut to avoid an extra memcpy() */ @@ -402,22 +414,8 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc) tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_curtile = tile; - if( td->td_stripbytecount[tile] > 0 ) - { - /* Make sure that at the first attempt of rewriting the tile, we will have */ - /* more bytes available in the output buffer than the previous byte count, */ - /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */ - /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */ - if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] ) - { - if( !(TIFFWriteBufferSetup(tif, NULL, - (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) ) - return ((tmsize_t)(-1)); - } - - /* Force TIFFAppendToStrip() to consider placing data at end - of file. */ - tif->tif_curoff = 0; + if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) { + return ((tmsize_t)(-1)); } tif->tif_rawcc = 0; @@ -537,20 +535,20 @@ TIFFSetupStrips(TIFF* tif) td->td_nstrips = td->td_stripsperimage; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; - td->td_stripoffset = (uint64 *) + td->td_stripoffset_p = (uint64 *) _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), "for \"StripOffsets\" array"); - td->td_stripbytecount = (uint64 *) + td->td_stripbytecount_p = (uint64 *) _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), "for \"StripByteCounts\" array"); - if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL) + if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL) return (0); /* * Place data at the end-of-file * (by setting offsets to zero). */ - _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); - _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); + _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64)); + _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64)); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); return (1); @@ -572,7 +570,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module) } if (tiles ^ isTiled(tif)) { TIFFErrorExt(tif->tif_clientdata, module, tiles ? - "Can not write tiles to a stripped image" : + "Can not write tiles to a striped image" : "Can not write scanlines to a tiled image"); return (0); } @@ -610,7 +608,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module) return (0); } } - if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) { + if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) { tif->tif_dir.td_nstrips = 0; TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", isTiled(tif) ? "tile" : "strip"); @@ -628,6 +626,20 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module) if (tif->tif_scanlinesize == 0) return (0); tif->tif_flags |= TIFF_BEENWRITING; + + if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && + tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && + tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && + tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 && + !(tif->tif_flags & TIFF_DIRTYDIRECT) ) + { + TIFFForceStrileArrayWriting(tif); + } + return (1); } @@ -684,9 +696,9 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) uint64* new_stripbytecount; assert(td->td_planarconfig == PLANARCONFIG_CONTIG); - new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset, + new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset_p, (td->td_nstrips + delta) * sizeof (uint64)); - new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount, + new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount_p, (td->td_nstrips + delta) * sizeof (uint64)); if (new_stripoffset == NULL || new_stripbytecount == NULL) { if (new_stripoffset) @@ -697,11 +709,11 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module) TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays"); return (0); } - td->td_stripoffset = new_stripoffset; - td->td_stripbytecount = new_stripbytecount; - _TIFFmemset(td->td_stripoffset + td->td_nstrips, + td->td_stripoffset_p = new_stripoffset; + td->td_stripbytecount_p = new_stripbytecount; + _TIFFmemset(td->td_stripoffset_p + td->td_nstrips, 0, delta*sizeof (uint64)); - _TIFFmemset(td->td_stripbytecount + td->td_nstrips, + _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips, 0, delta*sizeof (uint64)); td->td_nstrips += delta; tif->tif_flags |= TIFF_DIRTYDIRECT; @@ -720,12 +732,12 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) uint64 m; int64 old_byte_count = -1; - if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { + if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) { assert(td->td_nstrips > 0); - if( td->td_stripbytecount[strip] != 0 - && td->td_stripoffset[strip] != 0 - && td->td_stripbytecount[strip] >= (uint64) cc ) + if( td->td_stripbytecount_p[strip] != 0 + && td->td_stripoffset_p[strip] != 0 + && td->td_stripbytecount_p[strip] >= (uint64) cc ) { /* * There is already tile data on disk, and the new tile @@ -734,7 +746,7 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) * more data to append to this strip before we are done * depending on how we are getting called. */ - if (!SeekOK(tif, td->td_stripoffset[strip])) { + if (!SeekOK(tif, td->td_stripoffset_p[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu", (unsigned long)tif->tif_row); @@ -747,17 +759,17 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) * Seek to end of file, and set that as our location to * write this strip. */ - td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); + td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END); tif->tif_flags |= TIFF_DIRTYSTRIP; } - tif->tif_curoff = td->td_stripoffset[strip]; + tif->tif_curoff = td->td_stripoffset_p[strip]; /* * We are starting a fresh strip/tile, so set the size to zero. */ - old_byte_count = td->td_stripbytecount[strip]; - td->td_stripbytecount[strip] = 0; + old_byte_count = td->td_stripbytecount_p[strip]; + td->td_stripbytecount_p[strip] = 0; } m = tif->tif_curoff+cc; @@ -774,9 +786,9 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) return (0); } tif->tif_curoff = m; - td->td_stripbytecount[strip] += cc; + td->td_stripbytecount_p[strip] += cc; - if( (int64) td->td_stripbytecount[strip] != old_byte_count ) + if( (int64) td->td_stripbytecount_p[strip] != old_byte_count ) tif->tif_flags |= TIFF_DIRTYSTRIP; return (1); diff --git a/src/3rdparty/libtiff/libtiff/tif_zip.c b/src/3rdparty/libtiff/libtiff/tif_zip.c index 9d4bceb..c750773 100644 --- a/src/3rdparty/libtiff/libtiff/tif_zip.c +++ b/src/3rdparty/libtiff/libtiff/tif_zip.c @@ -124,7 +124,6 @@ ZIPSetupDecode(TIFF* tif) static int ZIPPreDecode(TIFF* tif, uint16 s) { - static const char module[] = "ZIPPreDecode"; ZIPState* sp = DecoderState(tif); (void) s; @@ -138,12 +137,7 @@ ZIPPreDecode(TIFF* tif, uint16 s) we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond appropriately even before we simplify it */ - sp->stream.avail_in = (uInt) tif->tif_rawcc; - if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } + sp->stream.avail_in = (uint64)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt) tif->tif_rawcc : 0xFFFFFFFFU; return (inflateReset(&sp->stream) == Z_OK); } @@ -158,46 +152,43 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s) assert(sp->state == ZSTATE_INIT_DECODE); sp->stream.next_in = tif->tif_rawcp; - sp->stream.avail_in = (uInt) tif->tif_rawcc; sp->stream.next_out = op; assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond appropriately even before we simplify it */ - sp->stream.avail_out = (uInt) occ; - if ((tmsize_t)sp->stream.avail_out != occ) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } do { - int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + int state; + uInt avail_in_before = (uint64)tif->tif_rawcc <= 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU; + uInt avail_out_before = (uint64)occ < 0xFFFFFFFFU ? (uInt) occ : 0xFFFFFFFFU; + sp->stream.avail_in = avail_in_before; + sp->stream.avail_out = avail_out_before; + state = inflate(&sp->stream, Z_PARTIAL_FLUSH); + tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in); + occ -= (avail_out_before - sp->stream.avail_out); if (state == Z_STREAM_END) break; if (state == Z_DATA_ERROR) { TIFFErrorExt(tif->tif_clientdata, module, "Decoding error at scanline %lu, %s", (unsigned long) tif->tif_row, SAFE_MSG(sp)); - if (inflateSync(&sp->stream) != Z_OK) - return (0); - continue; + return (0); } if (state != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", SAFE_MSG(sp)); return (0); } - } while (sp->stream.avail_out > 0); - if (sp->stream.avail_out != 0) { + } while (occ > 0); + if (occ != 0) { TIFFErrorExt(tif->tif_clientdata, module, "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", - (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out); + (unsigned long) tif->tif_row, (TIFF_UINT64_T) occ); return (0); } tif->tif_rawcp = sp->stream.next_in; - tif->tif_rawcc = sp->stream.avail_in; return (1); } @@ -229,7 +220,6 @@ ZIPSetupEncode(TIFF* tif) static int ZIPPreEncode(TIFF* tif, uint16 s) { - static const char module[] = "ZIPPreEncode"; ZIPState *sp = EncoderState(tif); (void) s; @@ -242,12 +232,7 @@ ZIPPreEncode(TIFF* tif, uint16 s) we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond appropriately even before we simplify it */ - sp->stream.avail_out = (uInt)tif->tif_rawdatasize; - if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } + sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU; return (deflateReset(&sp->stream) == Z_OK); } @@ -269,13 +254,9 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) we need to simplify this code to reflect a ZLib that is likely updated to deal with 8byte memory sizes, though this code will respond appropriately even before we simplify it */ - sp->stream.avail_in = (uInt) cc; - if ((tmsize_t)sp->stream.avail_in != cc) - { - TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size"); - return (0); - } do { + uInt avail_in_before = (uint64)cc <= 0xFFFFFFFFU ? (uInt)cc : 0xFFFFFFFFU; + sp->stream.avail_in = avail_in_before; if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s", @@ -286,9 +267,10 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s) tif->tif_rawcc = tif->tif_rawdatasize; TIFFFlushData1(tif); sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ + sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU; } - } while (sp->stream.avail_in > 0); + cc -= (avail_in_before - sp->stream.avail_in); + } while (cc > 0); return (1); } @@ -314,7 +296,7 @@ ZIPPostEncode(TIFF* tif) tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; TIFFFlushData1(tif); sp->stream.next_out = tif->tif_rawdata; - sp->stream.avail_out = (uInt) tif->tif_rawdatasize; /* this is a safe typecast, as check is made already in ZIPPreEncode */ + sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU; } break; default: diff --git a/src/3rdparty/libtiff/libtiff/tiffio.h b/src/3rdparty/libtiff/libtiff/tiffio.h index 31c2e67..198481d 100644 --- a/src/3rdparty/libtiff/libtiff/tiffio.h +++ b/src/3rdparty/libtiff/libtiff/tiffio.h @@ -411,6 +411,8 @@ extern int TIFFWriteDirectory(TIFF *); extern int TIFFWriteCustomDirectory(TIFF *, uint64 *); extern int TIFFCheckpointDirectory(TIFF *); extern int TIFFRewriteDirectory(TIFF *); +extern int TIFFDeferStrileArrayWriting(TIFF *); +extern int TIFFForceStrileArrayWriting(TIFF* ); #if defined(c_plusplus) || defined(__cplusplus) extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); @@ -468,6 +470,9 @@ extern tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_ extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size); extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size); +extern int TIFFReadFromUserBuffer(TIFF* tif, uint32 strile, + void* inbuf, tmsize_t insize, + void* outbuf, tmsize_t outsize); extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc); extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc); @@ -488,6 +493,11 @@ extern void TIFFSwabArrayOfDouble(double* dp, tmsize_t n); extern void TIFFReverseBits(uint8* cp, tmsize_t n); extern const unsigned char* TIFFGetBitRevTable(int); +extern uint64 TIFFGetStrileOffset(TIFF *tif, uint32 strile); +extern uint64 TIFFGetStrileByteCount(TIFF *tif, uint32 strile); +extern uint64 TIFFGetStrileOffsetWithErr(TIFF *tif, uint32 strile, int *pbErr); +extern uint64 TIFFGetStrileByteCountWithErr(TIFF *tif, uint32 strile, int *pbErr); + #ifdef LOGLUV_PUBLIC #define U_NEU 0.210526316 #define V_NEU 0.473684211 diff --git a/src/3rdparty/libtiff/libtiff/tiffiop.h b/src/3rdparty/libtiff/libtiff/tiffiop.h index 558484f..45a7932 100644 --- a/src/3rdparty/libtiff/libtiff/tiffiop.h +++ b/src/3rdparty/libtiff/libtiff/tiffiop.h @@ -80,6 +80,16 @@ extern int snprintf(char* str, size_t size, const char* format, ...); #define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0)) #define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1) +/* + * Largest 32-bit unsigned integer value. + */ +#define TIFF_UINT32_MAX 0xFFFFFFFFU + +/* + * Largest 64-bit unsigned integer value. + */ +#define TIFF_UINT64_MAX (((uint64)(TIFF_UINT32_MAX)) << 32 | TIFF_UINT32_MAX) + typedef struct client_info { struct client_info *next; void *data; @@ -130,6 +140,9 @@ struct tiff { #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/ #define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */ #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */ + #define TIFF_DEFERSTRILELOAD 0x1000000U /* defer strip/tile offset/bytecount array loading. */ + #define TIFF_LAZYSTRILELOAD 0x2000000U /* lazy/ondemand loading of strip/tile offset/bytecount values. Only used if TIFF_DEFERSTRILELOAD is set and in read-only mode */ + #define TIFF_CHOPPEDUPARRAYS 0x4000000U /* set when allocChoppedUpStripArrays() has modified strip array */ uint64 tif_diroff; /* file offset of current directory */ uint64 tif_nextdiroff; /* file offset of following directory */ uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ @@ -379,6 +392,8 @@ extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); extern double _TIFFUInt64ToDouble(uint64); extern float _TIFFUInt64ToFloat(uint64); +extern float _TIFFClampDoubleToFloat(double); + extern tmsize_t _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, void **buf, tmsize_t bufsizetoalloc, diff --git a/src/3rdparty/libtiff/libtiff/tiffvers.h b/src/3rdparty/libtiff/libtiff/tiffvers.h index 403d61b..aa3f613 100644 --- a/src/3rdparty/libtiff/libtiff/tiffvers.h +++ b/src/3rdparty/libtiff/libtiff/tiffvers.h @@ -1,4 +1,4 @@ -#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.10\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." +#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.1.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc." /* * This define can be used in code that requires * compilation-related definitions specific to a @@ -6,4 +6,4 @@ * version checking should be done based on the * string returned by TIFFGetVersion. */ -#define TIFFLIB_VERSION 20181110 +#define TIFFLIB_VERSION 20191103 diff --git a/src/3rdparty/libtiff/port/snprintf.c b/src/3rdparty/libtiff/port/snprintf.c index 1c4ac08..3542ab7 100644 --- a/src/3rdparty/libtiff/port/snprintf.c +++ b/src/3rdparty/libtiff/port/snprintf.c @@ -16,7 +16,11 @@ int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap) int count = -1; if (size != 0) +#if _MSC_VER <= 1310 + count = _vsnprintf(str, size, format, ap); +#else count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); +#endif if (count == -1) count = _vscprintf(format, ap); diff --git a/src/3rdparty/libtiff/qt_attribution.json b/src/3rdparty/libtiff/qt_attribution.json index e4f2db3..d51ee4a 100644 --- a/src/3rdparty/libtiff/qt_attribution.json +++ b/src/3rdparty/libtiff/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "", "Homepage": "http://www.simplesystems.org/libtiff/", - "Version": "4.0.10", + "Version": "4.1.0", "License": "libtiff License", "LicenseId": "libtiff", "LicenseFile": "COPYRIGHT", -- cgit v1.2.3