Merge remote-tracking branch 'origin/dev' into wip/cmake

Conflicts:
	dependencies.yaml

Change-Id: Ia9a6efda0bea5bc7c5f9f8cd4735da0bd3c0da26
This commit is contained in:
Alexandru Croitor 2020-03-16 17:07:23 +01:00
commit 51e7fa714c
70 changed files with 2931 additions and 988 deletions

View File

@ -1,6 +1,6 @@
load(qt_build_config) load(qt_build_config)
DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST DEFINES += QT_NO_FOREACH QT_NO_JAVA_STYLE_ITERATORS
MODULE_VERSION = 6.0.0 MODULE_VERSION = 6.0.0

25
dist/changes-5.13.2 vendored Normal file
View File

@ -0,0 +1,25 @@
Qt 5.13.2 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.13.0 through 5.13.1.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.13 series is binary compatible with the 5.12.x series.
Applications compiled for 5.12 will continue to run with 5.13.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* TIFF *
****************************************************************************
- Two security-related upstream patches has been applied to the
bundled libtiff

35
dist/changes-5.14.0 vendored Normal file
View File

@ -0,0 +1,35 @@
Qt 5.14 introduces many new features and improvements as well as bugfixes
over the 5.13.x series. For more details, refer to the online documentation
included in this distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.14 series is binary compatible with the 5.13.x series.
Applications compiled for 5.13 will continue to run with 5.14.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
****************************************************************************
* TIFF *
****************************************************************************
- Added support for reading and writing colorspace profiles
- Corrected 16 to 8 bit color channel conversion when reading color maps
****************************************************************************
* WEBP *
****************************************************************************
- Added support for reading and writing colorspace profiles
****************************************************************************
* Third-Party Code *
****************************************************************************
- Bundled libtiff was updated to version 4.1.0

20
dist/changes-5.14.1 vendored Normal file
View File

@ -0,0 +1,20 @@
Qt 5.14.1 is a bug-fix release. It maintains both forward and backward
compatibility (source and binary) with Qt 5.14.0.
For more details, refer to the online documentation included in this
distribution. The documentation is also available online:
https://doc.qt.io/qt-5/index.html
The Qt version 5.14 series is binary compatible with the 5.13.x series.
Applications compiled for 5.13 will continue to run with 5.14.
Some of the changes listed in this file include issue tracking numbers
corresponding to tasks in the Qt Bug Tracker:
https://bugreports.qt.io/
Each of these identifiers can be entered in the bug tracker to obtain more
information about a particular change.
- This release contains only minor code improvements.

View File

@ -1,3 +1,887 @@
2019-11-03 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
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 <even.rouault@spatialys.com>
tif_jpeg.c: extra cast to silence Coverity warning. GDAL CID 1406475.
2019-10-23 Even Rouault <even.rouault@spatialys.com>
tif_jpeg.c: fix warning added by previous commit (on 32bit builds)
2019-10-23 Even Rouault <even.rouault@spatialys.com>
Merge branch 'coverity-fixes' into 'master'
Coverity fixes
See merge request libtiff/libtiff!94
2019-10-22 Timothy Lyanguzov <timothy.lyanguzov@sap.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
HTML: update for GitLab issues.
2019-09-29 Even Rouault <even.rouault@spatialys.com>
html/v3.5.6-beta.html: redact URL of defunct web site.
Website: update links to mailing list.
2019-09-17 Even Rouault <even.rouault@spatialys.com>
TIFFReadAndRealloc(): avoid too large memory allocation attempts. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=17244
2019-09-03 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
tif_ojpeg.c: avoid unsigned integer overflow. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16793
2019-08-26 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
_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 <even.rouault@spatialys.com>
_TIFFMultiply32() / _TIFFMultiply64(): avoid relying on unsigned integer overflow (not a bug)
EstimateStripByteCounts(): avoid unsigned integer overflow.
2019-08-21 Even Rouault <even.rouault@spatialys.com>
EstimateStripByteCounts(): avoid unsigned integer overflow.
2019-08-20 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'patch-1' into 'master'
fix two tiny typos
See merge request libtiff/libtiff!89
2019-08-10 Reto Kromer <rk@reto.ch>
fix two tiny typos.
2019-08-09 Even Rouault <even.rouault@spatialys.com>
Merge branch 'patch-1' into 'master'
fix a typo in man page
See merge request libtiff/libtiff!88
2019-08-09 Reto Kromer <rk@reto.ch>
fix typo.
2019-08-04 Even Rouault <even.rouault@spatialys.com>
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 <sulau@freenet.de>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
TIFFWriteCheck(): call TIFFForceStrileArrayWriting() when needed (should have gone with eaeca6274ae71cdfaeb9f673b6fb0f3cfc0e6ce5) (master only)
2019-07-09 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <dirk@lemstra.org>
Return infinite distance when denominator is zero.
2019-06-29 Even Rouault <even.rouault@spatialys.com>
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 <miniupnp@free.fr>
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 <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
Merge branch 'defer_strile_writing' into 'master'
Add TIFFDeferStrileArrayWriting() and TIFFForceStrileArrayWriting()
See merge request libtiff/libtiff!82
2019-05-29 Even Rouault <even.rouault@spatialys.com>
Merge branch 'TIFFReadFromUserBuffer' into 'master'
Add TIFFReadFromUserBuffer()
See merge request libtiff/libtiff!81
2019-05-26 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Replace 'stripped' by 'striped' in error messages.
2019-05-25 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'html_link' into 'master'
libtiff.html, bigtiffpr.html: absolute => relative link
See merge request libtiff/libtiff!80
2019-05-14 Thomas Bernard <miniupnp@free.fr>
libtiff.html, bigtiffpr.html: absolute => relative link.
2019-05-10 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Creation: use SHORT type when possible for StripByteCounts/TileByteCounts
This follows the same logic as previous commit.
2019-05-09 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'bug2799' into 'master'
fix fax2tiff
See merge request libtiff/libtiff!55
2019-05-08 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <sulau@freenet.de>
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 <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'bug_2844' into 'master'
tiff2ps.c: PSDataColorContig(): avoid heap buffer overrun
See merge request libtiff/libtiff!69
2019-04-25 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'bug2848' into 'master'
tif_luv.c: LogLuvSetupEncode() error must return 0
See merge request libtiff/libtiff!72
2019-04-03 Thomas Bernard <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
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 <miniupnp@free.fr>
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 <miniupnp@free.fr>
add a test for fax2tiff tool.
2019-02-28 Thomas Bernard <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
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 <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
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 <miniupnp@free.fr>
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 <miniupnp@free.fr>
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 <even.rouault@spatialys.com>
Merge branch 'large_strile_improvements' into 'master'
Large strile support improvements
See merge request libtiff/libtiff!63
2019-02-21 Even Rouault <even.rouault@spatialys.com>
Merge branch 'gitlab-pages' into 'master'
ci: Add pages job
See merge request libtiff/libtiff!45
2019-02-19 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'issue_2842' into 'master'
move _TIFFClampDoubleToFloat() to tif_aux.c
See merge request libtiff/libtiff!62
2019-02-19 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'size_t_typo' into 'master'
CMakeLists.txt: fix TIFF_SIZE_T
See merge request libtiff/libtiff!59
2019-02-12 Thomas Bernard <miniupnp@free.fr>
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 <miniupnp@free.fr>
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 <miniupnp@free.fr>
tiffcp.c: use INT_MAX.
check that (Tile Width)*(Samples/Pixel) do no overflow.
fixes bug 2833
2019-02-03 Thomas Bernard <miniupnp@free.fr>
CMakeLists.txt: fix TIFF_SIZE_T.
2019-02-02 Even Rouault <even.rouault@spatialys.com>
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 <even.rouault@spatialys.com>
Merge branch 'bug2835' into 'master'
tiff2ps: fix heap-buffer-overflow
See merge request libtiff/libtiff!53
2019-02-02 Even Rouault <even.rouault@spatialys.com>
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 <yuri.aksenov@gmail.com>
fix fax2tiff.
see http://bugzilla.maptools.org/show_bug.cgi?id=2799
fixes d9bc8472e72549f29c0062c1cbd3d56f279f3be2
2019-02-02 Even Rouault <even.rouault@spatialys.com>
Merge branch 'tiffcrop' into 'master'
tiffcrop: shut up clang warnings
See merge request libtiff/libtiff!52
2019-02-01 Even Rouault <even.rouault@spatialys.com>
Merge branch 'bug2833' into 'master'
TIFFWriteDirectoryTagTransferfunction() : fix NULL dereferencing
See merge request libtiff/libtiff!54
2019-02-01 Even Rouault <even.rouault@spatialys.com>
Merge branch 'gitignore' into 'master'
add test/ files to .gitignore
See merge request libtiff/libtiff!56
2019-02-01 Even Rouault <even.rouault@spatialys.com>
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 <miniupnp@free.fr>
add test/ files to .gitignore.
2019-01-29 Thomas Bernard <miniupnp@free.fr>
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 <miniupnp@free.fr>
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 <miniupnp@free.fr>
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 <github.scott@gmail.com>
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 <bfriesen@simple.dallas.tx.us>
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 <hle@debian.org>
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 <bfriesen@simple.dallas.tx.us>
Do not attempt to re-sync zip stream after reported data error from inflate().
2018-12-07 Even Rouault <even.rouault@spatialys.com>
Merge branch 'resource-leaks' into 'master'
Fix two resource leaks
See merge request libtiff/libtiff!43
2018-12-07 Even Rouault <even.rouault@spatialys.com>
Merge branch 'build-jbig' into 'master'
add jbig support to the fuzzer
See merge request libtiff/libtiff!42
2018-12-01 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
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 <even.rouault@spatialys.com>
Merge branch 'webp_memleak' into 'master'
fixed mem leak in webp compression
See merge request libtiff/libtiff!48
2018-11-28 Norman Barker <norman.barker@mapbox.com>
fixed mem leak in webp compression.
2018-11-20 Even Rouault <even.rouault@spatialys.com>
Merge branch 'lossless_webp' into 'master'
fixed lossless webp compression config
See merge request libtiff/libtiff!46
2018-11-20 Norman Barker <norman.barker@mapbox.com>
fixed lossless webp compression config.
2018-11-18 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
snprintf porting fix for Visual Studio 2003.
2018-11-18 Roger Leigh <rleigh@codelibre.net>
ci: Add pages job.
2018-11-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
Change references from defunct ftp site to https site.
2018-11-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us> 2018-11-10 Bob Friesenhahn <bfriesen@simple.dallas.tx.us>
* configure.ac: libtiff 4.0.10 released. * configure.ac: libtiff 4.0.10 released.

View File

@ -1 +1 @@
20181110 20191103

View File

@ -1 +1 @@
4.0.10 4.1.0

View File

@ -20,6 +20,7 @@ EXPORTS TIFFAccessTagMethods
TIFFDataWidth TIFFDataWidth
TIFFDefaultStripSize TIFFDefaultStripSize
TIFFDefaultTileSize TIFFDefaultTileSize
TIFFDeferStrileArrayWriting
TIFFError TIFFError
TIFFErrorExt TIFFErrorExt
TIFFFdOpen TIFFFdOpen
@ -37,6 +38,7 @@ EXPORTS TIFFAccessTagMethods
TIFFFindField TIFFFindField
TIFFFlush TIFFFlush
TIFFFlushData TIFFFlushData
TIFFForceStrileArrayWriting
TIFFFreeDirectory TIFFFreeDirectory
TIFFGetBitRevTable TIFFGetBitRevTable
TIFFGetClientInfo TIFFGetClientInfo
@ -49,6 +51,10 @@ EXPORTS TIFFAccessTagMethods
TIFFGetReadProc TIFFGetReadProc
TIFFGetSeekProc TIFFGetSeekProc
TIFFGetSizeProc TIFFGetSizeProc
TIFFGetStrileByteCount
TIFFGetStrileByteCountWithErr
TIFFGetStrileOffset
TIFFGetStrileOffsetWithErr
TIFFGetTagListCount TIFFGetTagListCount
TIFFGetTagListEntry TIFFGetTagListEntry
TIFFGetUnmapFileProc TIFFGetUnmapFileProc
@ -82,6 +88,7 @@ EXPORTS TIFFAccessTagMethods
TIFFReadEXIFDirectory TIFFReadEXIFDirectory
TIFFReadEncodedStrip TIFFReadEncodedStrip
TIFFReadEncodedTile TIFFReadEncodedTile
TIFFReadFromUserBuffer
TIFFReadRGBAImage TIFFReadRGBAImage
TIFFReadRGBAImageOriented TIFFReadRGBAImageOriented
TIFFReadRGBAStrip TIFFReadRGBAStrip

View File

@ -40,7 +40,7 @@
#include "tif_fax3.h" #include "tif_fax3.h"
#ifndef HAVE_GETOPT #ifndef HAVE_GETOPT
extern int getopt(int, char**, char*); extern int getopt(int argc, char * const argv[], const char *optstring);
#endif #endif
#define streq(a,b) (strcmp(a,b) == 0) #define streq(a,b) (strcmp(a,b) == 0)

View File

@ -30,31 +30,66 @@
#include "tiffiop.h" #include "tiffiop.h"
#include "tif_predict.h" #include "tif_predict.h"
#include <math.h> #include <math.h>
#include <float.h>
uint32 uint32
_TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where) _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where)
{ {
uint32 bytes = first * second; if (second && first > TIFF_UINT32_MAX / second) {
if (second && bytes / second != first) {
TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
bytes = 0; return 0;
} }
return bytes; return first * second;
} }
uint64 uint64
_TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where) _TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where)
{ {
uint64 bytes = first * second; if (second && first > TIFF_UINT64_MAX / second) {
if (second && bytes / second != first) {
TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where); TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
bytes = 0; return 0;
} }
return bytes; return first * second;
}
tmsize_t
_TIFFMultiplySSize(TIFF* tif, tmsize_t first, tmsize_t second, const char* where)
{
if( first <= 0 || second <= 0 )
{
if( tif != NULL && where != NULL )
{
TIFFErrorExt(tif->tif_clientdata, where,
"Invalid argument to _TIFFMultiplySSize() in %s", where);
}
return 0;
}
if( first > TIFF_TMSIZE_T_MAX / second )
{
if( tif != NULL && where != NULL )
{
TIFFErrorExt(tif->tif_clientdata, where,
"Integer overflow in %s", where);
}
return 0;
}
return first * second;
}
tmsize_t _TIFFCastUInt64ToSSize(TIFF* tif, uint64 val, const char* module)
{
if( val > (uint64)TIFF_TMSIZE_T_MAX )
{
if( tif != NULL && module != NULL )
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
}
return 0;
}
return (tmsize_t)val;
} }
void* void*
@ -62,13 +97,14 @@ _TIFFCheckRealloc(TIFF* tif, void* buffer,
tmsize_t nmemb, tmsize_t elem_size, const char* what) tmsize_t nmemb, tmsize_t elem_size, const char* what)
{ {
void* cp = NULL; void* cp = NULL;
tmsize_t bytes = nmemb * elem_size; tmsize_t count = _TIFFMultiplySSize(tif, nmemb, elem_size, NULL);
/* /*
* XXX: Check for integer overflow. * Check for integer overflow.
*/ */
if (nmemb && elem_size && bytes / elem_size == nmemb) if (count != 0)
cp = _TIFFrealloc(buffer, bytes); {
cp = _TIFFrealloc(buffer, count);
}
if (cp == NULL) { if (cp == NULL) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
@ -357,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) int _TIFFSeekOK(TIFF* tif, toff_t off)
{ {
/* Huge offsets, especially -1 / UINT64_MAX, can cause issues */ /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */

View File

@ -32,7 +32,7 @@
packages produce RGBA files but don't mark the alpha properly. */ packages produce RGBA files but don't mark the alpha properly. */
/* #undef DEFAULT_EXTRASAMPLE_AS_ALPHA */ /* #undef DEFAULT_EXTRASAMPLE_AS_ALPHA */
/* enable deferred strip/tile offset/size loading (experimental) */ /* enable deferred strip/tile offset/size loading */
/* #undef DEFER_STRILE_LOAD */ /* #undef DEFER_STRILE_LOAD */
/* Define to 1 if you have the <assert.h> header file. */ /* Define to 1 if you have the <assert.h> header file. */

View File

@ -21,7 +21,7 @@
packages produce RGBA files but don't mark the alpha properly. */ packages produce RGBA files but don't mark the alpha properly. */
#undef DEFAULT_EXTRASAMPLE_AS_ALPHA #undef DEFAULT_EXTRASAMPLE_AS_ALPHA
/* enable deferred strip/tile offset/size loading (experimental) */ /* enable deferred strip/tile offset/size loading */
#undef DEFER_STRILE_LOAD #undef DEFER_STRILE_LOAD
/* Define to 1 if you have the <assert.h> header file. */ /* Define to 1 if you have the <assert.h> header file. */

View File

@ -29,7 +29,6 @@
* (and also some miscellaneous stuff) * (and also some miscellaneous stuff)
*/ */
#include "tiffiop.h" #include "tiffiop.h"
#include <float.h>
/* /*
* These are used in the backwards compatibility code... * 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; *vpp = 0;
} }
if (vp) { if (vp) {
tmsize_t bytes = (tmsize_t)(nmemb * elem_size); tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
if (elem_size && bytes / elem_size == nmemb) if (bytes)
*vpp = (void*) _TIFFmalloc(bytes); *vpp = (void*) _TIFFmalloc(bytes);
if (*vpp) if (*vpp)
_TIFFmemcpy(*vpp, vp, bytes); _TIFFmemcpy(*vpp, vp, bytes);
@ -88,13 +87,15 @@ setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
* Install extra samples information. * Install extra samples information.
*/ */
static int 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 */ /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
#define EXTRASAMPLE_COREL_UNASSALPHA 999 #define EXTRASAMPLE_COREL_UNASSALPHA 999
uint16* va; uint16* va;
uint32 i; uint32 i;
TIFFDirectory* td = &tif->tif_dir;
static const char module[] = "setExtraSamples";
*v = (uint16) va_arg(ap, uint16_vap); *v = (uint16) va_arg(ap, uint16_vap);
if ((uint16) *v > td->td_samplesperpixel) if ((uint16) *v > td->td_samplesperpixel)
@ -116,6 +117,18 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
return 0; 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; td->td_extrasamples = (uint16) *v;
_TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples); _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
return 1; return 1;
@ -153,15 +166,6 @@ bad:
return (0); 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 static int
_TIFFVSetField(TIFF* tif, uint32 tag, va_list ap) _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
{ {
@ -285,6 +289,18 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
_TIFFfree(td->td_smaxsamplevalue); _TIFFfree(td->td_smaxsamplevalue);
td->td_smaxsamplevalue = NULL; 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; td->td_samplesperpixel = (uint16) v;
break; break;
@ -320,13 +336,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_xresolution = TIFFClampDoubleToFloat( dblval ); td->td_xresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_YRESOLUTION: case TIFFTAG_YRESOLUTION:
dblval = va_arg(ap, double); dblval = va_arg(ap, double);
if( dblval < 0 ) if( dblval < 0 )
goto badvaluedouble; goto badvaluedouble;
td->td_yresolution = TIFFClampDoubleToFloat( dblval ); td->td_yresolution = _TIFFClampDoubleToFloat( dblval );
break; break;
case TIFFTAG_PLANARCONFIG: case TIFFTAG_PLANARCONFIG:
v = (uint16) va_arg(ap, uint16_vap); v = (uint16) va_arg(ap, uint16_vap);
@ -335,10 +351,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
td->td_planarconfig = (uint16) v; td->td_planarconfig = (uint16) v;
break; break;
case TIFFTAG_XPOSITION: case TIFFTAG_XPOSITION:
td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_YPOSITION: case TIFFTAG_YPOSITION:
td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) ); td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
break; break;
case TIFFTAG_RESOLUTIONUNIT: case TIFFTAG_RESOLUTIONUNIT:
v = (uint16) va_arg(ap, uint16_vap); 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); _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
break; break;
case TIFFTAG_EXTRASAMPLES: case TIFFTAG_EXTRASAMPLES:
if (!setExtraSamples(td, ap, &v)) if (!setExtraSamples(tif, ap, &v))
goto badvalue; goto badvalue;
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
@ -684,7 +700,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
case TIFF_SRATIONAL: case TIFF_SRATIONAL:
case TIFF_FLOAT: case TIFF_FLOAT:
{ {
float v2 = TIFFClampDoubleToFloat(va_arg(ap, double)); float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double));
_TIFFmemcpy(val, &v2, tv_size); _TIFFmemcpy(val, &v2, tv_size);
} }
break; break;
@ -1002,12 +1018,12 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
case TIFFTAG_STRIPOFFSETS: case TIFFTAG_STRIPOFFSETS:
case TIFFTAG_TILEOFFSETS: case TIFFTAG_TILEOFFSETS:
_TIFFFillStriles( tif ); _TIFFFillStriles( tif );
*va_arg(ap, uint64**) = td->td_stripoffset; *va_arg(ap, uint64**) = td->td_stripoffset_p;
break; break;
case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_STRIPBYTECOUNTS:
case TIFFTAG_TILEBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS:
_TIFFFillStriles( tif ); _TIFFFillStriles( tif );
*va_arg(ap, uint64**) = td->td_stripbytecount; *va_arg(ap, uint64**) = td->td_stripbytecount_p;
break; break;
case TIFFTAG_MATTEING: case TIFFTAG_MATTEING:
*va_arg(ap, uint16*) = *va_arg(ap, uint16*) =
@ -1266,8 +1282,9 @@ TIFFFreeDirectory(TIFF* tif)
CleanupField(td_transferfunction[0]); CleanupField(td_transferfunction[0]);
CleanupField(td_transferfunction[1]); CleanupField(td_transferfunction[1]);
CleanupField(td_transferfunction[2]); CleanupField(td_transferfunction[2]);
CleanupField(td_stripoffset); CleanupField(td_stripoffset_p);
CleanupField(td_stripbytecount); CleanupField(td_stripbytecount_p);
td->td_stripoffsetbyteallocsize = 0;
TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING); TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING); TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
@ -1280,10 +1297,8 @@ TIFFFreeDirectory(TIFF* tif)
td->td_customValueCount = 0; td->td_customValueCount = 0;
CleanupField(td_customValues); CleanupField(td_customValues);
#if defined(DEFER_STRILE_LOAD)
_TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
_TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry)); _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
#endif
} }
#undef CleanupField #undef CleanupField
@ -1371,7 +1386,9 @@ TIFFDefaultDirectory(TIFF* tif)
td->td_tilewidth = 0; td->td_tilewidth = 0;
td->td_tilelength = 0; td->td_tilelength = 0;
td->td_tiledepth = 1; td->td_tiledepth = 1;
#ifdef STRIPBYTECOUNTSORTED_UNUSED
td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */ td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */
#endif
td->td_resolutionunit = RESUNIT_INCH; td->td_resolutionunit = RESUNIT_INCH;
td->td_sampleformat = SAMPLEFORMAT_UINT; td->td_sampleformat = SAMPLEFORMAT_UINT;
td->td_imagedepth = 1; td->td_imagedepth = 1;

View File

@ -58,6 +58,7 @@ typedef struct {
uint32 toff_long; uint32 toff_long;
uint64 toff_long8; uint64 toff_long8;
} tdir_offset; /* either offset or the data itself if fits */ } 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; } TIFFDirEntry;
/* /*
@ -97,13 +98,14 @@ typedef struct {
* number of striles */ * number of striles */
uint32 td_stripsperimage; uint32 td_stripsperimage;
uint32 td_nstrips; /* size of offset & bytecount arrays */ uint32 td_nstrips; /* size of offset & bytecount arrays */
uint64* td_stripoffset; uint64* td_stripoffset_p; /* should be accessed with TIFFGetStrileOffset */
uint64* td_stripbytecount; 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? */ int td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
#if defined(DEFER_STRILE_LOAD) #endif
TIFFDirEntry td_stripoffset_entry; /* for deferred loading */ TIFFDirEntry td_stripoffset_entry; /* for deferred loading */
TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */ TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
#endif
uint16 td_nsubifd; uint16 td_nsubifd;
uint64* td_subifd; uint64* td_subifd;
/* YCbCr parameters */ /* YCbCr parameters */
@ -118,6 +120,8 @@ typedef struct {
int td_customValueCount; int td_customValueCount;
TIFFTagValue *td_customValues; TIFFTagValue *td_customValues;
unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
} TIFFDirectory; } TIFFDirectory;
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,6 @@
* Directory Write Support Routines. * Directory Write Support Routines.
*/ */
#include "tiffiop.h" #include "tiffiop.h"
#include <float.h>
#ifdef HAVE_IEEEFP #ifdef HAVE_IEEEFP
#define TIFFCvtNativeToIEEEFloat(tif, n, fp) #define TIFFCvtNativeToIEEEFloat(tif, n, fp)
@ -182,6 +181,51 @@ TIFFWriteDirectory(TIFF* tif)
return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL); 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 * Similar to TIFFWriteDirectory(), writes the directory out
* but leaves all data structures in memory so that it can be * but leaves all data structures in memory so that it can be
@ -193,7 +237,7 @@ TIFFCheckpointDirectory(TIFF* tif)
{ {
int rc; int rc;
/* Setup the strips arrays, if they haven't already been. */ /* 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); (void) TIFFSetupStrips(tif);
rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL); rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL);
(void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END)); (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 (!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; goto bad;
} }
else 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; goto bad;
} }
} }
@ -541,7 +585,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
{ {
if (!isTiled(tif)) 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. * tif_dirread.c around line 3634.
* XXX: OJPEG hack. * XXX: OJPEG hack.
* If a) compression is OJPEG, b) it's not a tiled TIFF, * 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. * We can get here when using tiffset on such a file.
* See http://bugzilla.maptools.org/show_bug.cgi?id=2500 * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
*/ */
if (tif->tif_dir.td_stripoffset != NULL && if (tif->tif_dir.td_stripoffset_p != NULL &&
!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset)) !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p))
goto bad; goto bad;
} }
else 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; goto bad;
} }
} }
@ -946,15 +990,6 @@ bad:
return(0); 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 ) static int8 TIFFClampDoubleToInt8( double val )
{ {
if( val > 127 ) if( val > 127 )
@ -1029,7 +1064,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
if (tif->tif_dir.td_bitspersample<=32) if (tif->tif_dir.td_bitspersample<=32)
{ {
for (i = 0; i < count; ++i) 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); ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
} }
else else
@ -1661,22 +1696,52 @@ TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1
return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value)); 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() */ /* TIFFWriteDirectoryTagLongLong8Array() */
/* */ /* */
/* Write out LONG8 array as LONG8 for BigTIFF or LONG for */ /* Write out LONG8 array and write a SHORT/LONG/LONG8 depending */
/* Classic TIFF with some checking. */ /* on strile size and Classic/BigTIFF mode. */
/************************************************************************/ /************************************************************************/
static int static int
TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value) TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
{ {
static const char module[] = "TIFFWriteDirectoryTagLongLong8Array"; static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
uint64* ma;
uint32 mb;
uint32* p;
uint32* q;
int o; int o;
int write_aslong4;
/* is this just a counting pass? */ /* is this just a counting pass? */
if (dir==NULL) if (dir==NULL)
@ -1685,37 +1750,105 @@ TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
return(1); return(1);
} }
/* We always write LONG8 for BigTIFF, no checking needed. */ if( tif->tif_dir.td_deferstrilearraywriting )
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.
*/
p = _TIFFmalloc(count*sizeof(uint32));
if (p==NULL)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL);
return(0);
} }
for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++) if( tif->tif_flags&TIFF_BIGTIFF )
{ {
if (*ma>0xFFFFFFFF) 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 )
{ {
TIFFErrorExt(tif->tif_clientdata,module, write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
"Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file."); }
_TIFFfree(p); else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
{
write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
}
if( write_aslong8 )
{
return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
tag,count,value);
}
}
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 )
{
/*
** 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,"Out of memory");
return(0); return(0);
} }
*q= (uint32)(*ma);
}
o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p); for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
_TIFFfree(p); {
if (*ma>0xFFFFFFFF)
{
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;
if (p==NULL)
{
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
return(0);
}
for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
{
if (*ma>0xFFFF)
{
/* 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); return(o);
} }
@ -1893,12 +2026,14 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir
n=3; n=3;
if (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; n=2;
} }
if (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; n=1;
} }
if (n==0) if (n==0)
@ -2428,7 +2563,12 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag
dir[m].tdir_count=count; dir[m].tdir_count=count;
dir[m].tdir_offset.toff_long8 = 0; dir[m].tdir_offset.toff_long8 = 0;
if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U)) 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 else
{ {
uint64 na,nb; uint64 na,nb;
@ -2820,13 +2960,60 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
TIFFSwabLong8( &entry_offset ); 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? */ /* What data type do we want to write this as? */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) ) if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) )
{ {
if( in_datatype == TIFF_LONG8 ) if( in_datatype == TIFF_LONG8 )
datatype = TIFF_LONG; datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG;
else if( in_datatype == TIFF_SLONG8 ) else if( in_datatype == TIFF_SLONG8 )
datatype = TIFF_SLONG; datatype = TIFF_SLONG;
else if( in_datatype == TIFF_IFD8 ) else if( in_datatype == TIFF_IFD8 )
@ -2834,8 +3021,21 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
else else
datatype = in_datatype; datatype = in_datatype;
} }
else else
datatype = in_datatype; {
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 */ /* 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) ) 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 */ /* If the tag type, and count match, then we just write it out */
/* over the old values without altering the directory entry at */ /* 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. */ /* Adjust the directory entry. */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
entry_type = datatype; entry_type = datatype;
entry_count = (uint64)count;
memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) ); memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) );
if (tif->tif_flags&TIFF_SWAB) if (tif->tif_flags&TIFF_SWAB)
TIFFSwabShort( (uint16 *) (direntry_raw + 2) ); TIFFSwabShort( (uint16 *) (direntry_raw + 2) );

View File

@ -45,36 +45,8 @@ TIFFFlush(TIFF* tif)
&& !(tif->tif_flags & TIFF_DIRTYDIRECT) && !(tif->tif_flags & TIFF_DIRTYDIRECT)
&& tif->tif_mode == O_RDWR ) && tif->tif_mode == O_RDWR )
{ {
uint64 *offsets=NULL, *sizes=NULL; if( TIFFForceStrileArrayWriting(tif) )
return 1;
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 ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP))
@ -84,6 +56,92 @@ TIFFFlush(TIFF* tif)
return (1); 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. * Flush buffered data to the file.
* *

View File

@ -755,9 +755,8 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
uint32 leftmost_tw; uint32 leftmost_tw;
tilesize = TIFFTileSize(tif); tilesize = TIFFTileSize(tif);
bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize); bufsize = _TIFFMultiplySSize(tif, alpha?4:3,tilesize, "gtTileSeparate");
if (bufsize == 0) { if (bufsize == 0) {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate");
return (0); return (0);
} }
@ -950,16 +949,23 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
fromskew = (w < imagewidth ? imagewidth - w : 0); fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow) for (row = 0; row < h; row += nrow)
{ {
uint32 temp;
rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
nrow = (row + rowstoread > h ? h - row : rowstoread); nrow = (row + rowstoread > h ? h - row : rowstoread);
nrowsub = nrow; nrowsub = nrow;
if ((nrowsub%subsamplingver)!=0) if ((nrowsub%subsamplingver)!=0)
nrowsub+=subsamplingver-nrowsub%subsamplingver; nrowsub+=subsamplingver-nrowsub%subsamplingver;
temp = (row + img->row_offset)%rowsperstrip + nrowsub;
if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
{
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripContig");
return 0;
}
if (_TIFFReadEncodedStripAndAllocBuffer(tif, if (_TIFFReadEncodedStripAndAllocBuffer(tif,
TIFFComputeStrip(tif,row+img->row_offset, 0), TIFFComputeStrip(tif,row+img->row_offset, 0),
(void**)(&buf), (void**)(&buf),
maxstripsize, maxstripsize,
((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1) temp * scanline)==(tmsize_t)(-1)
&& (buf == NULL || img->stoponerr)) && (buf == NULL || img->stoponerr))
{ {
ret = 0; ret = 0;
@ -1019,9 +1025,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
uint16 colorchannels; uint16 colorchannels;
stripsize = TIFFStripSize(tif); stripsize = TIFFStripSize(tif);
bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize); bufsize = _TIFFMultiplySSize(tif,alpha?4:3,stripsize, "gtStripSeparate");
if (bufsize == 0) { if (bufsize == 0) {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate");
return (0); return (0);
} }
@ -1053,15 +1058,22 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
fromskew = (w < imagewidth ? imagewidth - w : 0); fromskew = (w < imagewidth ? imagewidth - w : 0);
for (row = 0; row < h; row += nrow) for (row = 0; row < h; row += nrow)
{ {
uint32 temp;
rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
nrow = (row + rowstoread > h ? h - row : rowstoread); nrow = (row + rowstoread > h ? h - row : rowstoread);
offset_row = row + img->row_offset; offset_row = row + img->row_offset;
temp = (row + img->row_offset)%rowsperstrip + nrow;
if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
{
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripSeparate");
return 0;
}
if( buf == NULL ) if( buf == NULL )
{ {
if (_TIFFReadEncodedStripAndAllocBuffer( if (_TIFFReadEncodedStripAndAllocBuffer(
tif, TIFFComputeStrip(tif, offset_row, 0), tif, TIFFComputeStrip(tif, offset_row, 0),
(void**) &buf, bufsize, (void**) &buf, bufsize,
((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) temp * scanline)==(tmsize_t)(-1)
&& (buf == NULL || img->stoponerr)) && (buf == NULL || img->stoponerr))
{ {
ret = 0; ret = 0;
@ -1081,7 +1093,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
} }
else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0), else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) p0, temp * scanline)==(tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1089,7 +1101,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
if (colorchannels > 1 if (colorchannels > 1
&& TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1), && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) p1, temp * scanline) == (tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1097,7 +1109,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
} }
if (colorchannels > 1 if (colorchannels > 1
&& TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2), && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1) p2, temp * scanline) == (tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -1106,7 +1118,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
if (alpha) if (alpha)
{ {
if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels), if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels),
pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1) pa, temp * scanline)==(tmsize_t)(-1)
&& img->stoponerr) && img->stoponerr)
{ {
ret = 0; ret = 0;
@ -2957,7 +2969,7 @@ TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop
if( !TIFFIsTiled( tif ) ) if( !TIFFIsTiled( tif ) )
{ {
TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
"Can't use TIFFReadRGBATile() with stripped file."); "Can't use TIFFReadRGBATile() with striped file.");
return (0); return (0);
} }

View File

@ -780,12 +780,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
*/ */
static const char module[] = "JPEGFixupTagsSubsampling"; static const char module[] = "JPEGFixupTagsSubsampling";
struct JPEGFixupTagsSubsamplingData m; struct JPEGFixupTagsSubsamplingData m;
uint64 fileoffset = TIFFGetStrileOffset(tif, 0);
_TIFFFillStriles( tif ); if( fileoffset == 0 )
if( tif->tif_dir.td_stripbytecount == NULL
|| tif->tif_dir.td_stripoffset == NULL
|| tif->tif_dir.td_stripbytecount[0] == 0 )
{ {
/* Do not even try to check if the first strip/tile does not /* 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 yet exist, as occurs when GDAL has created a new NULL file
@ -804,9 +801,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
} }
m.buffercurrentbyte=NULL; m.buffercurrentbyte=NULL;
m.bufferbytesleft=0; m.bufferbytesleft=0;
m.fileoffset=tif->tif_dir.td_stripoffset[0]; m.fileoffset=fileoffset;
m.filepositioned=0; m.filepositioned=0;
m.filebytesleft=tif->tif_dir.td_stripbytecount[0]; m.filebytesleft=TIFFGetStrileByteCount(tif, 0);
if (!JPEGFixupTagsSubsamplingSec(&m)) if (!JPEGFixupTagsSubsamplingSec(&m))
TIFFWarningExt(tif->tif_clientdata,module, TIFFWarningExt(tif->tif_clientdata,module,
"Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped"); "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; JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;
#else #else
JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset; 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", TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
"application buffer not large enough for all data, possible subsampling issue"); "application buffer not large enough for all data, possible subsampling issue");
return 0; 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 */ /* data is expected to be supplied in multiples of a clumpline */
/* a clumpline is equivalent to v_sampling desubsampled scanlines */ /* 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 */ /* 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) bytesperclumpline = ((((tmsize_t)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) *((tmsize_t)sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
/8; /8;
nrows = ( cc / bytesperclumpline ) * sp->v_sampling; nrows = ( cc / bytesperclumpline ) * sp->v_sampling;

View File

@ -742,9 +742,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
#undef exp2 /* Conflict with C'99 function */ #undef exp2 /* Conflict with C'99 function */
#define exp2(x) exp(M_LN2*(x)) #define exp2(x) exp(M_LN2*(x))
#define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \ static int itrunc(double x, int m)
(int)(x) : \ {
(int)((x) + rand()*(1./RAND_MAX) - .5)) 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 #if !LOGLUV_PUBLIC
static static
@ -1264,16 +1269,10 @@ LogL16GuessDataFmt(TIFFDirectory *td)
return (SGILOGDATAFMT_UNKNOWN); return (SGILOGDATAFMT_UNKNOWN);
} }
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
static tmsize_t static tmsize_t
multiply_ms(tmsize_t m1, tmsize_t m2) multiply_ms(tmsize_t m1, tmsize_t m2)
{ {
if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) return _TIFFMultiplySSize(NULL, m1, m2, NULL);
return 0;
return m1 * m2;
} }
static int static int
@ -1507,7 +1506,7 @@ LogLuvSetupEncode(TIFF* tif)
switch (td->td_photometric) { switch (td->td_photometric) {
case PHOTOMETRIC_LOGLUV: case PHOTOMETRIC_LOGLUV:
if (!LogLuvInitState(tif)) if (!LogLuvInitState(tif))
break; return (0);
if (td->td_compression == COMPRESSION_SGILOG24) { if (td->td_compression == COMPRESSION_SGILOG24) {
tif->tif_encoderow = LogLuvEncode24; tif->tif_encoderow = LogLuvEncode24;
switch (sp->user_datafmt) { switch (sp->user_datafmt) {
@ -1540,7 +1539,7 @@ LogLuvSetupEncode(TIFF* tif)
break; break;
case PHOTOMETRIC_LOGL: case PHOTOMETRIC_LOGL:
if (!LogL16InitState(tif)) if (!LogL16InitState(tif))
break; return (0);
tif->tif_encoderow = LogL16Encode; tif->tif_encoderow = LogL16Encode;
switch (sp->user_datafmt) { switch (sp->user_datafmt) {
case SGILOGDATAFMT_FLOAT: case SGILOGDATAFMT_FLOAT:
@ -1556,7 +1555,7 @@ LogLuvSetupEncode(TIFF* tif)
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Inappropriate photometric interpretation %d for SGILog compression; %s", "Inappropriate photometric interpretation %d for SGILog compression; %s",
td->td_photometric, "must be either LogLUV or LogL"); td->td_photometric, "must be either LogLUV or LogL");
break; return (0);
} }
sp->encoder_state = 1; sp->encoder_state = 1;
return (1); return (1);

View File

@ -247,6 +247,8 @@ LZWSetupDecode(TIFF* tif)
/* /*
* Zero-out the unused entries * Zero-out the unused entries
*/ */
/* Silence false positive */
/* coverity[overrun-buffer-arg] */
_TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0, _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0,
(CODE_FIRST - CODE_CLEAR) * sizeof (code_t)); (CODE_FIRST - CODE_CLEAR) * sizeof (code_t));
} }

View File

@ -243,6 +243,7 @@ typedef enum {
typedef struct { typedef struct {
TIFF* tif; TIFF* tif;
int decoder_ok; int decoder_ok;
int error_in_raw_data_decoding;
#ifndef LIBJPEG_ENCAP_EXTERNAL #ifndef LIBJPEG_ENCAP_EXTERNAL
JMP_BUF exit_jmpbuf; JMP_BUF exit_jmpbuf;
#endif #endif
@ -678,7 +679,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s)
if (OJPEGReadSecondarySos(tif,s)==0) if (OJPEGReadSecondarySos(tif,s)==0)
return(0); return(0);
} }
if isTiled(tif) if (isTiled(tif))
m=tif->tif_curtile; m=tif->tif_curtile;
else else
m=tif->tif_curstrip; m=tif->tif_curstrip;
@ -742,6 +743,7 @@ OJPEGPreDecodeSkipRaw(TIFF* tif)
} }
m-=sp->subsampling_convert_clines-sp->subsampling_convert_state; m-=sp->subsampling_convert_clines-sp->subsampling_convert_state;
sp->subsampling_convert_state=0; sp->subsampling_convert_state=0;
sp->error_in_raw_data_decoding=0;
} }
while (m>=sp->subsampling_convert_clines) 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"); TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized");
return 0; return 0;
} }
if( sp->error_in_raw_data_decoding )
{
return 0;
}
if (sp->libjpeg_jpeg_query_style==0) if (sp->libjpeg_jpeg_query_style==0)
{ {
if (OJPEGDecodeRaw(tif,buf,cc)==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) if (sp->subsampling_convert_state==0)
{ {
if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==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); 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; 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; 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; OJPEGState* sp=(OJPEGState*)tif->tif_data;
uint8 mh; uint8 mh;
uint8 mv; uint8 mv;
_TIFFFillStriles( tif );
assert(sp->subsamplingcorrect_done==0); assert(sp->subsamplingcorrect_done==0);
if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) && 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); assert(sp->readheader_done==0);
sp->image_width=tif->tif_dir.td_imagewidth; sp->image_width=tif->tif_dir.td_imagewidth;
sp->image_length=tif->tif_dir.td_imagelength; sp->image_length=tif->tif_dir.td_imagelength;
if isTiled(tif) if (isTiled(tif))
{ {
sp->strile_width=tif->tif_dir.td_tilewidth; sp->strile_width=tif->tif_dir.td_tilewidth;
sp->strile_length=tif->tif_dir.td_tilelength; sp->strile_length=tif->tif_dir.td_tilelength;
@ -1082,6 +1120,12 @@ OJPEGReadHeaderInfo(TIFF* tif)
} }
if (sp->strile_length<sp->image_length) if (sp->strile_length<sp->image_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) if (sp->strile_length%(sp->subsampling_ver*8)!=0)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length"); 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_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines; 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_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) if (sp->subsampling_convert_ycbcrbuf==0)
{ {
TIFFErrorExt(tif->tif_clientdata,module,"Out of memory"); 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; *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen;
for (n=0; n<sp->subsampling_convert_clines; n++) for (n=0; n<sp->subsampling_convert_clines; n++)
*m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen; *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->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->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; sp->subsampling_convert_log=1;
} }
} }
@ -1272,7 +1323,9 @@ OJPEGReadHeaderInfoSec(TIFF* tif)
} }
else 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; sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format;
} }
} }
@ -1989,32 +2042,30 @@ OJPEGReadBufferFill(OJPEGState* sp)
sp->in_buffer_source=osibsStrile; sp->in_buffer_source=osibsStrile;
break; break;
case osibsStrile: 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) if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
sp->in_buffer_source=osibsEof; sp->in_buffer_source=osibsEof;
else 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) 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) if (sp->in_buffer_file_pos>=sp->file_size)
sp->in_buffer_file_pos=0; 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; sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
else else
{ {
if (sp->tif->tif_dir.td_stripbytecount == 0) { sp->in_buffer_file_togo=bytecount;
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];
if (sp->in_buffer_file_togo==0) if (sp->in_buffer_file_togo==0)
sp->in_buffer_file_pos=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; sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
} }
} }

View File

@ -131,6 +131,7 @@ TIFFClientOpen(
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) { if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
TIFFErrorExt(clientdata, module, TIFFErrorExt(clientdata, module,
"One of the client procedures is NULL pointer."); "One of the client procedures is NULL pointer.");
_TIFFfree(tif);
goto bad2; goto bad2;
} }
tif->tif_readproc = readproc; tif->tif_readproc = readproc;
@ -181,6 +182,8 @@ TIFFClientOpen(
* 'h' read TIFF header only, do not load the first IFD * 'h' read TIFF header only, do not load the first IFD
* '4' ClassicTIFF for creating a file (default) * '4' ClassicTIFF for creating a file (default)
* '8' BigTIFF for creating a file * '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. * The use of the 'l' and 'b' flags is strongly discouraged.
* These flags are provided solely because numerous vendors, * These flags are provided solely because numerous vendors,
@ -262,7 +265,22 @@ TIFFClientOpen(
if (m&O_CREAT) if (m&O_CREAT)
tif->tif_flags |= TIFF_BIGTIFF; tif->tif_flags |= TIFF_BIGTIFF;
break; 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. * Read in TIFF header.
*/ */

View File

@ -634,20 +634,16 @@ PixarLogGuessDataFmt(TIFFDirectory *td)
return guess; return guess;
} }
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
static tmsize_t static tmsize_t
multiply_ms(tmsize_t m1, tmsize_t m2) multiply_ms(tmsize_t m1, tmsize_t m2)
{ {
if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 ) return _TIFFMultiplySSize(NULL, m1, m2, NULL);
return 0;
return m1 * m2;
} }
static tmsize_t static tmsize_t
add_ms(tmsize_t m1, tmsize_t m2) add_ms(tmsize_t m1, tmsize_t m2)
{ {
assert(m1 >= 0 && m2 >= 0);
/* if either input is zero, assume overflow already occurred */ /* if either input is zero, assume overflow already occurred */
if (m1 == 0 || m2 == 0) if (m1 == 0 || m2 == 0)
return 0; return 0;
@ -817,9 +813,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)"); (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
if (inflateSync(&sp->stream) != Z_OK) return (0);
return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s", TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
@ -1153,7 +1147,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
llen = sp->stride * td->td_imagewidth; llen = sp->stride * td->td_imagewidth;
/* Check against the number of elements (of size uint16) of sp->tbuf */ /* 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, TIFFErrorExt(tif->tif_clientdata, module,
"Too many input bytes provided"); "Too many input bytes provided");

View File

@ -652,8 +652,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
if (tif->tif_tagmethods.printdir) if (tif->tif_tagmethods.printdir)
(*tif->tif_tagmethods.printdir)(tif, fd, flags); (*tif->tif_tagmethods.printdir)(tif, fd, flags);
_TIFFFillStriles( tif );
if ((flags & TIFFPRINT_STRIPS) && if ((flags & TIFFPRINT_STRIPS) &&
TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) { TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
uint32 s; uint32 s;
@ -665,13 +663,13 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
fprintf(fd, " %3lu: [%8I64u, %8I64u]\n", fprintf(fd, " %3lu: [%8I64u, %8I64u]\n",
(unsigned long) s, (unsigned long) s,
td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0, (unsigned __int64) TIFFGetStrileOffset(tif, s),
td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0); (unsigned __int64) TIFFGetStrileByteCount(tif, s));
#else #else
fprintf(fd, " %3lu: [%8llu, %8llu]\n", fprintf(fd, " %3lu: [%8llu, %8llu]\n",
(unsigned long) s, (unsigned long) s,
td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0, (unsigned long long) TIFFGetStrileOffset(tif, s),
td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0); (unsigned long long) TIFFGetStrileByteCount(tif, s));
#endif #endif
} }
} }

View File

@ -29,9 +29,6 @@
#include "tiffiop.h" #include "tiffiop.h"
#include <stdio.h> #include <stdio.h>
#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
int TIFFFillStrip(TIFF* tif, uint32 strip); int TIFFFillStrip(TIFF* tif, uint32 strip);
int TIFFFillTile(TIFF* tif, uint32 tile); int TIFFFillTile(TIFF* tif, uint32 tile);
static int TIFFStartStrip(TIFF* tif, uint32 strip); static int TIFFStartStrip(TIFF* tif, uint32 strip);
@ -49,6 +46,8 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
#define THRESHOLD_MULTIPLIER 10 #define THRESHOLD_MULTIPLIER 10
#define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD) #define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD)
#define TIFF_INT64_MAX ((((int64)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
/* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' /* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset'
* Returns 1 in case of success, 0 otherwise. */ * Returns 1 in case of success, 0 otherwise. */
static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
@ -61,6 +60,22 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
#endif #endif
tmsize_t already_read = 0; 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 */ /* 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 */ /* 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 */ /* short. We could ask for the file size, but this might be */
@ -103,6 +118,11 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
} }
tif->tif_rawdata = new_rawdata; tif->tif_rawdata = new_rawdata;
} }
if( tif->tif_rawdata == NULL )
{
/* should not happen in practice but helps CoverityScan */
return 0;
}
bytes_read = TIFFReadFile(tif, bytes_read = TIFFReadFile(tif,
tif->tif_rawdata + rawdata_offset + already_read, to_read); tif->tif_rawdata + rawdata_offset + already_read, to_read);
@ -170,17 +190,14 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
tmsize_t to_read; tmsize_t to_read;
tmsize_t read_ahead_mod; tmsize_t read_ahead_mod;
/* tmsize_t bytecountm; */ /* tmsize_t bytecountm; */
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
/* /*
* Expand raw data buffer, if needed, to hold data * Expand raw data buffer, if needed, to hold data
* strip coming from file (perhaps should set upper * strip coming from file (perhaps should set upper
* bound on the size of a buffer we'll use?). * 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 */ /* Not completely sure where the * 2 comes from, but probably for */
/* an exponentional growth strategy of tif_rawdatasize */ /* an exponentional growth strategy of tif_rawdatasize */
@ -224,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. ** 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; + tif->tif_rawdataoff + tif->tif_rawdataloaded;
if (!SeekOK(tif, read_offset)) { if (!SeekOK(tif, read_offset)) {
@ -241,10 +258,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
to_read = read_ahead_mod - unused_data; to_read = read_ahead_mod - unused_data;
else else
to_read = tif->tif_rawdatasize - unused_data; 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 ) - 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; - tif->tif_rawdataoff - tif->tif_rawdataloaded;
} }
@ -283,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 */ /* For JPEG, if there are multiple scans (can generally be known */
/* with the read_ahead used), we need to read the whole strip */ /* with the read_ahead used), we need to read the whole strip */
if( tif->tif_dir.td_compression==COMPRESSION_JPEG && 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) ) if( TIFFJPEGIsFullStripRequired(tif) )
{ {
@ -342,9 +359,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
* read it a few lines at a time? * read it a few lines at a time?
*/ */
#if defined(CHUNKY_STRIP_READ_SUPPORT) #if defined(CHUNKY_STRIP_READ_SUPPORT)
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) whole_strip = TIFFGetStrileByteCount(tif, strip) < 10
return 0;
whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
|| isMapped(tif); || isMapped(tif);
if( td->td_compression == COMPRESSION_LERC || if( td->td_compression == COMPRESSION_LERC ||
td->td_compression == COMPRESSION_JBIG ) td->td_compression == COMPRESSION_JBIG )
@ -397,7 +412,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
else if( !whole_strip ) else if( !whole_strip )
{ {
if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead 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) ) if( !TIFFFillStripPartial(tif,strip,read_ahead,0) )
return 0; return 0;
@ -594,16 +609,11 @@ static tmsize_t
TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
const char* module) const char* module)
{ {
TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ))
return ((tmsize_t)(-1));
assert((tif->tif_flags&TIFF_NOREADRAW)==0); assert((tif->tif_flags&TIFF_NOREADRAW)==0);
if (!isMapped(tif)) { if (!isMapped(tif)) {
tmsize_t cc; tmsize_t cc;
if (!SeekOK(tif, td->td_stripoffset[strip])) { if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip))) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at scanline %lu, strip %lu", "Seek error at scanline %lu, strip %lu",
(unsigned long) tif->tif_row, (unsigned long) strip); (unsigned long) tif->tif_row, (unsigned long) strip);
@ -629,8 +639,8 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
} else { } else {
tmsize_t ma = 0; tmsize_t ma = 0;
tmsize_t n; tmsize_t n;
if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| if ((TIFFGetStrileOffset(tif, strip) > (uint64)TIFF_TMSIZE_T_MAX)||
((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) ((ma=(tmsize_t)TIFFGetStrileOffset(tif, strip))>tif->tif_size))
{ {
n=0; n=0;
} }
@ -674,12 +684,10 @@ static tmsize_t
TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip,
tmsize_t size, const char* module) tmsize_t size, const char* module)
{ {
TIFFDirectory *td = &tif->tif_dir;
assert( !isMapped(tif) ); assert( !isMapped(tif) );
assert((tif->tif_flags&TIFF_NOREADRAW)==0); 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 ) if( is_strip )
{ {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -715,7 +723,7 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
{ {
static const char module[] = "TIFFReadRawStrip"; static const char module[] = "TIFFReadRawStrip";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint64 bytecount; uint64 bytecount64;
tmsize_t bytecountm; tmsize_t bytecountm;
if (!TIFFCheckRead(tif, 0)) if (!TIFFCheckRead(tif, 0))
@ -733,31 +741,23 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
"Compression scheme does not support access to raw uncompressed data"); "Compression scheme does not support access to raw uncompressed data");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
bytecount = td->td_stripbytecount[strip]; bytecount64 = TIFFGetStrileByteCount(tif, strip);
if ((int64)bytecount <= 0) { if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module,
"%I64u: Invalid strip byte count, strip %lu",
(unsigned __int64) bytecount,
(unsigned long) strip);
#else
TIFFErrorExt(tif->tif_clientdata, module,
"%llu: Invalid strip byte count, strip %lu",
(unsigned long long) bytecount,
(unsigned long) strip);
#endif
return ((tmsize_t)(-1));
}
bytecountm = (tmsize_t)bytecount;
if ((uint64)bytecountm!=bytecount) {
TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow");
return ((tmsize_t)(-1));
}
if (size != (tmsize_t)(-1) && size < bytecountm)
bytecountm = size; bytecountm = size;
else
bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
if( bytecountm == 0 ) {
return ((tmsize_t)(-1));
}
return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module)); 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 * Read the specified strip and setup for decoding. The data buffer is
* expanded, as necessary, to hold the strip's data. * expanded, as necessary, to hold the strip's data.
@ -768,13 +768,10 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
static const char module[] = "TIFFFillStrip"; static const char module[] = "TIFFFillStrip";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags&TIFF_NOREADRAW)==0) if ((tif->tif_flags&TIFF_NOREADRAW)==0)
{ {
uint64 bytecount = td->td_stripbytecount[strip]; uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
if ((int64)bytecount <= 0) { if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Invalid strip byte count %I64u, strip %lu", "Invalid strip byte count %I64u, strip %lu",
@ -801,7 +798,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
(bytecount - 4096) / 10 > (uint64)stripsize ) (bytecount - 4096) / 10 > (uint64)stripsize )
{ {
uint64 newbytecount = (uint64)stripsize * 10 + 4096; uint64 newbytecount = (uint64)stripsize * 10 + 4096;
if( (int64)newbytecount >= 0 ) if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
{ {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFWarningExt(tif->tif_clientdata, module, TIFFWarningExt(tif->tif_clientdata, module,
@ -826,13 +823,13 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
* We must check for overflow, potentially causing * We must check for overflow, potentially causing
* an OOB read. Instead of simple * 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 * comparison (which can overflow) we do the following
* two comparisons: * two comparisons:
*/ */
if (bytecount > (uint64)tif->tif_size || 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 * This error message might seem strange, but
* it's what would happen if a read were done * it's what would happen if a read were done
@ -844,7 +841,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
"Read error on strip %lu; " "Read error on strip %lu; "
"got %I64u bytes, expected %I64u", "got %I64u bytes, expected %I64u",
(unsigned long) strip, (unsigned long) strip,
(unsigned __int64) tif->tif_size - td->td_stripoffset[strip], (unsigned __int64) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)),
(unsigned __int64) bytecount); (unsigned __int64) bytecount);
#else #else
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
@ -852,7 +849,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
"Read error on strip %lu; " "Read error on strip %lu; "
"got %llu bytes, expected %llu", "got %llu bytes, expected %llu",
(unsigned long) strip, (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); (unsigned long long) bytecount);
#endif #endif
tif->tif_curstrip = NOSTRIP; tif->tif_curstrip = NOSTRIP;
@ -881,7 +878,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
} }
tif->tif_flags &= ~TIFF_MYBUFFER; tif->tif_flags &= ~TIFF_MYBUFFER;
tif->tif_rawdatasize = (tmsize_t)bytecount; 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_rawdataoff = 0;
tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_rawdataloaded = (tmsize_t) bytecount;
@ -1096,16 +1093,11 @@ _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile,
static tmsize_t static tmsize_t
TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) 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); assert((tif->tif_flags&TIFF_NOREADRAW)==0);
if (!isMapped(tif)) { if (!isMapped(tif)) {
tmsize_t cc; tmsize_t cc;
if (!SeekOK(tif, td->td_stripoffset[tile])) { if (!SeekOK(tif, TIFFGetStrileOffset(tif, tile))) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at row %lu, col %lu, tile %lu", "Seek error at row %lu, col %lu, tile %lu",
(unsigned long) tif->tif_row, (unsigned long) tif->tif_row,
@ -1135,9 +1127,9 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
} else { } else {
tmsize_t ma,mb; tmsize_t ma,mb;
tmsize_t n; tmsize_t n;
ma=(tmsize_t)td->td_stripoffset[tile]; ma=(tmsize_t)TIFFGetStrileOffset(tif, tile);
mb=ma+size; 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; n=0;
else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
n=tif->tif_size-ma; n=tif->tif_size-ma;
@ -1193,13 +1185,12 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size)
"Compression scheme does not support access to raw uncompressed data"); "Compression scheme does not support access to raw uncompressed data");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
bytecount64 = td->td_stripbytecount[tile]; bytecount64 = TIFFGetStrileByteCount(tif, tile);
if (size != (tmsize_t)(-1) && (uint64)size < bytecount64) if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
bytecount64 = (uint64)size; bytecountm = size;
bytecountm = (tmsize_t)bytecount64; else
if ((uint64)bytecountm!=bytecount64) bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
{ if( bytecountm == 0 ) {
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
return ((tmsize_t)(-1)); return ((tmsize_t)(-1));
} }
return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module)); return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module));
@ -1215,13 +1206,10 @@ TIFFFillTile(TIFF* tif, uint32 tile)
static const char module[] = "TIFFFillTile"; static const char module[] = "TIFFFillTile";
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags&TIFF_NOREADRAW)==0) if ((tif->tif_flags&TIFF_NOREADRAW)==0)
{ {
uint64 bytecount = td->td_stripbytecount[tile]; uint64 bytecount = TIFFGetStrileByteCount(tif, tile);
if ((int64)bytecount <= 0) { if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"%I64u: Invalid tile byte count, tile %lu", "%I64u: Invalid tile byte count, tile %lu",
@ -1248,7 +1236,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
(bytecount - 4096) / 10 > (uint64)stripsize ) (bytecount - 4096) / 10 > (uint64)stripsize )
{ {
uint64 newbytecount = (uint64)stripsize * 10 + 4096; uint64 newbytecount = (uint64)stripsize * 10 + 4096;
if( (int64)newbytecount >= 0 ) if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
{ {
#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
TIFFWarningExt(tif->tif_clientdata, module, TIFFWarningExt(tif->tif_clientdata, module,
@ -1273,13 +1261,13 @@ TIFFFillTile(TIFF* tif, uint32 tile)
* We must check for overflow, potentially causing * We must check for overflow, potentially causing
* an OOB read. Instead of simple * 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 * comparison (which can overflow) we do the following
* two comparisons: * two comparisons:
*/ */
if (bytecount > (uint64)tif->tif_size || 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; tif->tif_curtile = NOTILE;
return (0); return (0);
} }
@ -1308,7 +1296,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
tif->tif_rawdatasize = (tmsize_t)bytecount; tif->tif_rawdatasize = (tmsize_t)bytecount;
tif->tif_rawdata = 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_rawdataoff = 0;
tif->tif_rawdataloaded = (tmsize_t) bytecount; tif->tif_rawdataloaded = (tmsize_t) bytecount;
tif->tif_flags |= TIFF_BUFFERMMAP; tif->tif_flags |= TIFF_BUFFERMMAP;
@ -1367,7 +1355,8 @@ TIFFFillTile(TIFF* tif, uint32 tile)
tif->tif_rawdataoff = 0; tif->tif_rawdataoff = 0;
tif->tif_rawdataloaded = bytecountm; 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) (tif->tif_flags & TIFF_NOBITREV) == 0)
TIFFReverseBits(tif->tif_rawdata, TIFFReverseBits(tif->tif_rawdata,
tif->tif_rawdataloaded); tif->tif_rawdataloaded);
@ -1434,9 +1423,6 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
{ {
TIFFDirectory *td = &tif->tif_dir; 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_flags & TIFF_CODERSETUP) == 0) {
if (!(*tif->tif_setupdecode)(tif)) if (!(*tif->tif_setupdecode)(tif))
return (0); return (0);
@ -1457,7 +1443,7 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
if( tif->tif_rawdataloaded > 0 ) if( tif->tif_rawdataloaded > 0 )
tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcc = tif->tif_rawdataloaded;
else else
tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip]; tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, strip);
} }
return ((*tif->tif_predecode)(tif, return ((*tif->tif_predecode)(tif,
(uint16)(strip / td->td_stripsperimage))); (uint16)(strip / td->td_stripsperimage)));
@ -1474,9 +1460,6 @@ TIFFStartTile(TIFF* tif, uint32 tile)
TIFFDirectory *td = &tif->tif_dir; TIFFDirectory *td = &tif->tif_dir;
uint32 howmany32; uint32 howmany32;
if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
return 0;
if ((tif->tif_flags & TIFF_CODERSETUP) == 0) { if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
if (!(*tif->tif_setupdecode)(tif)) if (!(*tif->tif_setupdecode)(tif))
return (0); return (0);
@ -1507,7 +1490,7 @@ TIFFStartTile(TIFF* tif, uint32 tile)
if( tif->tif_rawdataloaded > 0 ) if( tif->tif_rawdataloaded > 0 )
tif->tif_rawcc = tif->tif_rawdataloaded; tif->tif_rawcc = tif->tif_rawdataloaded;
else else
tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile]; tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, tile);
} }
return ((*tif->tif_predecode)(tif, return ((*tif->tif_predecode)(tif,
(uint16)(tile/td->td_stripsperimage))); (uint16)(tile/td->td_stripsperimage)));
@ -1522,13 +1505,100 @@ TIFFCheckRead(TIFF* tif, int tiles)
} }
if (tiles ^ isTiled(tif)) { if (tiles ^ isTiled(tif)) {
TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ? 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"); "Can not read scanlines from a tiled image");
return (0); return (0);
} }
return (1); 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 void
_TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc) _TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc)
{ {

View File

@ -129,15 +129,8 @@ TIFFVStripSize(TIFF* tif, uint32 nrows)
{ {
static const char module[] = "TIFFVStripSize"; static const char module[] = "TIFFVStripSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFVStripSize64(tif,nrows); m=TIFFVStripSize64(tif,nrows);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -147,8 +140,7 @@ uint64
TIFFRawStripSize64(TIFF* tif, uint32 strip) TIFFRawStripSize64(TIFF* tif, uint32 strip)
{ {
static const char module[] = "TIFFRawStripSize64"; static const char module[] = "TIFFRawStripSize64";
TIFFDirectory* td = &tif->tif_dir; uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
uint64 bytecount = td->td_stripbytecount[strip];
if (bytecount == 0) if (bytecount == 0)
{ {
@ -211,15 +203,8 @@ TIFFStripSize(TIFF* tif)
{ {
static const char module[] = "TIFFStripSize"; static const char module[] = "TIFFStripSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFStripSize64(tif); m=TIFFStripSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -330,14 +315,8 @@ TIFFScanlineSize(TIFF* tif)
{ {
static const char module[] = "TIFFScanlineSize"; static const char module[] = "TIFFScanlineSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFScanlineSize64(tif); m=TIFFScanlineSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m) {
TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
n=0;
}
return(n);
} }
/* /*
@ -366,15 +345,8 @@ TIFFRasterScanlineSize(TIFF* tif)
{ {
static const char module[] = "TIFFRasterScanlineSize"; static const char module[] = "TIFFRasterScanlineSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFRasterScanlineSize64(tif); m=TIFFRasterScanlineSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
n=0;
}
return(n);
} }
/* vim: set ts=8 sts=8 sw=8 noet: */ /* vim: set ts=8 sts=8 sw=8 noet: */

View File

@ -122,17 +122,17 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
break; break;
case THUNDER_2BITDELTAS: /* 2-bit deltas */ case THUNDER_2BITDELTAS: /* 2-bit deltas */
if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP) 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) 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) if ((delta = (n & 3)) != DELTA2_SKIP)
SETPIXEL(op, lastpixel + twobitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
break; break;
case THUNDER_3BITDELTAS: /* 3-bit deltas */ case THUNDER_3BITDELTAS: /* 3-bit deltas */
if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP) 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) if ((delta = (n & 7)) != DELTA3_SKIP)
SETPIXEL(op, lastpixel + threebitdeltas[delta]); SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta]));
break; break;
case THUNDER_RAW: /* raw data */ case THUNDER_RAW: /* raw data */
SETPIXEL(op, n); SETPIXEL(op, n);

View File

@ -181,15 +181,8 @@ TIFFTileRowSize(TIFF* tif)
{ {
static const char module[] = "TIFFTileRowSize"; static const char module[] = "TIFFTileRowSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFTileRowSize64(tif); m=TIFFTileRowSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -248,15 +241,8 @@ TIFFVTileSize(TIFF* tif, uint32 nrows)
{ {
static const char module[] = "TIFFVTileSize"; static const char module[] = "TIFFVTileSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFVTileSize64(tif,nrows); m=TIFFVTileSize64(tif,nrows);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*
@ -272,15 +258,8 @@ TIFFTileSize(TIFF* tif)
{ {
static const char module[] = "TIFFTileSize"; static const char module[] = "TIFFTileSize";
uint64 m; uint64 m;
tmsize_t n;
m=TIFFTileSize64(tif); m=TIFFTileSize64(tif);
n=(tmsize_t)m; return _TIFFCastUInt64ToSSize(tif, m, module);
if ((uint64)n!=m)
{
TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
n=0;
}
return(n);
} }
/* /*

View File

@ -128,10 +128,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
tif->tif_rawcc = 0; tif->tif_rawcc = 0;
tif->tif_rawcp = tif->tif_rawdata; 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 */ /* 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 */ /* this forces TIFFAppendToStrip() to do a seek */
tif->tif_curoff = 0; tif->tif_curoff = 0;
@ -176,6 +176,32 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
return (status); 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 * Encode the supplied data and write it to the
* specified strip. * specified strip.
@ -222,6 +248,13 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_BUF4WRITE; tif->tif_flags |= TIFF_BUF4WRITE;
tif->tif_curstrip = strip; 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) { if (td->td_stripsperimage == 0) {
TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image"); TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
return ((tmsize_t) -1); return ((tmsize_t) -1);
@ -234,27 +267,6 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
tif->tif_flags |= TIFF_CODERSETUP; 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; tif->tif_flags &= ~TIFF_POSTENCODE;
/* shortcut to avoid an extra memcpy() */ /* 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_flags |= TIFF_BUF4WRITE;
tif->tif_curtile = tile; tif->tif_curtile = tile;
if( td->td_stripbytecount[tile] > 0 ) if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
{ return ((tmsize_t)(-1));
/* 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;
} }
tif->tif_rawcc = 0; tif->tif_rawcc = 0;
@ -537,20 +535,20 @@ TIFFSetupStrips(TIFF* tif)
td->td_nstrips = td->td_stripsperimage; td->td_nstrips = td->td_stripsperimage;
if (td->td_planarconfig == PLANARCONFIG_SEPARATE) if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
td->td_stripsperimage /= td->td_samplesperpixel; td->td_stripsperimage /= td->td_samplesperpixel;
td->td_stripoffset = (uint64 *) td->td_stripoffset_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripOffsets\" array"); "for \"StripOffsets\" array");
td->td_stripbytecount = (uint64 *) td->td_stripbytecount_p = (uint64 *)
_TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64), _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
"for \"StripByteCounts\" array"); "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); return (0);
/* /*
* Place data at the end-of-file * Place data at the end-of-file
* (by setting offsets to zero). * (by setting offsets to zero).
*/ */
_TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64));
_TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64)); _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64));
TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS); TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS); TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
return (1); return (1);
@ -572,7 +570,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
} }
if (tiles ^ isTiled(tif)) { if (tiles ^ isTiled(tif)) {
TIFFErrorExt(tif->tif_clientdata, module, tiles ? 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"); "Can not write scanlines to a tiled image");
return (0); return (0);
} }
@ -610,7 +608,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
return (0); 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; tif->tif_dir.td_nstrips = 0;
TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays", TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
isTiled(tif) ? "tile" : "strip"); isTiled(tif) ? "tile" : "strip");
@ -628,6 +626,20 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
if (tif->tif_scanlinesize == 0) if (tif->tif_scanlinesize == 0)
return (0); return (0);
tif->tif_flags |= TIFF_BEENWRITING; 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); return (1);
} }
@ -684,9 +696,9 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
uint64* new_stripbytecount; uint64* new_stripbytecount;
assert(td->td_planarconfig == PLANARCONFIG_CONTIG); 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)); (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)); (td->td_nstrips + delta) * sizeof (uint64));
if (new_stripoffset == NULL || new_stripbytecount == NULL) { if (new_stripoffset == NULL || new_stripbytecount == NULL) {
if (new_stripoffset) 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"); TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
return (0); return (0);
} }
td->td_stripoffset = new_stripoffset; td->td_stripoffset_p = new_stripoffset;
td->td_stripbytecount = new_stripbytecount; td->td_stripbytecount_p = new_stripbytecount;
_TIFFmemset(td->td_stripoffset + td->td_nstrips, _TIFFmemset(td->td_stripoffset_p + td->td_nstrips,
0, delta*sizeof (uint64)); 0, delta*sizeof (uint64));
_TIFFmemset(td->td_stripbytecount + td->td_nstrips, _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips,
0, delta*sizeof (uint64)); 0, delta*sizeof (uint64));
td->td_nstrips += delta; td->td_nstrips += delta;
tif->tif_flags |= TIFF_DIRTYDIRECT; tif->tif_flags |= TIFF_DIRTYDIRECT;
@ -720,12 +732,12 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
uint64 m; uint64 m;
int64 old_byte_count = -1; 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); assert(td->td_nstrips > 0);
if( td->td_stripbytecount[strip] != 0 if( td->td_stripbytecount_p[strip] != 0
&& td->td_stripoffset[strip] != 0 && td->td_stripoffset_p[strip] != 0
&& td->td_stripbytecount[strip] >= (uint64) cc ) && td->td_stripbytecount_p[strip] >= (uint64) cc )
{ {
/* /*
* There is already tile data on disk, and the new tile * 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 * more data to append to this strip before we are done
* depending on how we are getting called. * 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, TIFFErrorExt(tif->tif_clientdata, module,
"Seek error at scanline %lu", "Seek error at scanline %lu",
(unsigned long)tif->tif_row); (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 * Seek to end of file, and set that as our location to
* write this strip. * 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_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. * We are starting a fresh strip/tile, so set the size to zero.
*/ */
old_byte_count = td->td_stripbytecount[strip]; old_byte_count = td->td_stripbytecount_p[strip];
td->td_stripbytecount[strip] = 0; td->td_stripbytecount_p[strip] = 0;
} }
m = tif->tif_curoff+cc; m = tif->tif_curoff+cc;
@ -774,9 +786,9 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
return (0); return (0);
} }
tif->tif_curoff = m; 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; tif->tif_flags |= TIFF_DIRTYSTRIP;
return (1); return (1);

View File

@ -124,7 +124,6 @@ ZIPSetupDecode(TIFF* tif)
static int static int
ZIPPreDecode(TIFF* tif, uint16 s) ZIPPreDecode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreDecode";
ZIPState* sp = DecoderState(tif); ZIPState* sp = DecoderState(tif);
(void) s; (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 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_in = (uInt) tif->tif_rawcc; sp->stream.avail_in = (uint64)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt) tif->tif_rawcc : 0xFFFFFFFFU;
if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
return (inflateReset(&sp->stream) == Z_OK); 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); assert(sp->state == ZSTATE_INIT_DECODE);
sp->stream.next_in = tif->tif_rawcp; sp->stream.next_in = tif->tif_rawcp;
sp->stream.avail_in = (uInt) tif->tif_rawcc;
sp->stream.next_out = op; sp->stream.next_out = op;
assert(sizeof(sp->stream.avail_out)==4); /* if this assert gets raised, 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 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ 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 { 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) if (state == Z_STREAM_END)
break; break;
if (state == Z_DATA_ERROR) { if (state == Z_DATA_ERROR) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Decoding error at scanline %lu, %s", "Decoding error at scanline %lu, %s",
(unsigned long) tif->tif_row, SAFE_MSG(sp)); (unsigned long) tif->tif_row, SAFE_MSG(sp));
if (inflateSync(&sp->stream) != Z_OK) return (0);
return (0);
continue;
} }
if (state != Z_OK) { if (state != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"ZLib error: %s", SAFE_MSG(sp)); "ZLib error: %s", SAFE_MSG(sp));
return (0); return (0);
} }
} while (sp->stream.avail_out > 0); } while (occ > 0);
if (sp->stream.avail_out != 0) { if (occ != 0) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)", "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); return (0);
} }
tif->tif_rawcp = sp->stream.next_in; tif->tif_rawcp = sp->stream.next_in;
tif->tif_rawcc = sp->stream.avail_in;
return (1); return (1);
} }
@ -229,7 +220,6 @@ ZIPSetupEncode(TIFF* tif)
static int static int
ZIPPreEncode(TIFF* tif, uint16 s) ZIPPreEncode(TIFF* tif, uint16 s)
{ {
static const char module[] = "ZIPPreEncode";
ZIPState *sp = EncoderState(tif); ZIPState *sp = EncoderState(tif);
(void) s; (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 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ appropriately even before we simplify it */
sp->stream.avail_out = (uInt)tif->tif_rawdatasize; sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
{
TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
return (0);
}
return (deflateReset(&sp->stream) == Z_OK); 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 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 to deal with 8byte memory sizes, though this code will respond
appropriately even before we simplify it */ 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 { 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) { if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
TIFFErrorExt(tif->tif_clientdata, module, TIFFErrorExt(tif->tif_clientdata, module,
"Encoder error: %s", "Encoder error: %s",
@ -286,9 +267,10 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
tif->tif_rawcc = tif->tif_rawdatasize; tif->tif_rawcc = tif->tif_rawdatasize;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; 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); return (1);
} }
@ -314,7 +296,7 @@ ZIPPostEncode(TIFF* tif)
tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out; tif->tif_rawcc = tif->tif_rawdatasize - sp->stream.avail_out;
TIFFFlushData1(tif); TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata; 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; break;
default: default:

View File

@ -411,6 +411,8 @@ extern int TIFFWriteDirectory(TIFF *);
extern int TIFFWriteCustomDirectory(TIFF *, uint64 *); extern int TIFFWriteCustomDirectory(TIFF *, uint64 *);
extern int TIFFCheckpointDirectory(TIFF *); extern int TIFFCheckpointDirectory(TIFF *);
extern int TIFFRewriteDirectory(TIFF *); extern int TIFFRewriteDirectory(TIFF *);
extern int TIFFDeferStrileArrayWriting(TIFF *);
extern int TIFFForceStrileArrayWriting(TIFF* );
#if defined(c_plusplus) || defined(__cplusplus) #if defined(c_plusplus) || defined(__cplusplus)
extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0); 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 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 TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);
extern tmsize_t TIFFReadRawTile(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 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 TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, 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 void TIFFReverseBits(uint8* cp, tmsize_t n);
extern const unsigned char* TIFFGetBitRevTable(int); 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 #ifdef LOGLUV_PUBLIC
#define U_NEU 0.210526316 #define U_NEU 0.210526316
#define V_NEU 0.473684211 #define V_NEU 0.473684211

View File

@ -77,6 +77,19 @@ extern int snprintf(char* str, size_t size, const char* format, ...);
#define FALSE 0 #define FALSE 0
#endif #endif
#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 { typedef struct client_info {
struct client_info *next; struct client_info *next;
void *data; void *data;
@ -127,6 +140,9 @@ struct tiff {
#define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/ #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/
#define TIFF_PERSAMPLE 0x400000U /* get/set per sample tags as arrays */ #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_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_diroff; /* file offset of current directory */
uint64 tif_nextdiroff; /* file offset of following directory */ uint64 tif_nextdiroff; /* file offset of following directory */
uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */ uint64* tif_dirlist; /* list of offsets to already seen directories to prevent IFD looping */
@ -258,7 +274,7 @@ struct tiff {
#define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3) #define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3)
#define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y)) #define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y))
/* Safe multiply which returns zero if there is an integer overflow */ /* Safe multiply which returns zero if there is an *unsigned* integer overflow. This macro is not safe for *signed* integer types */
#define TIFFSafeMultiply(t,v,m) ((((t)(m) != (t)0) && (((t)(((v)*(m))/(m))) == (t)(v))) ? (t)((v)*(m)) : (t)0) #define TIFFSafeMultiply(t,v,m) ((((t)(m) != (t)0) && (((t)(((v)*(m))/(m))) == (t)(v))) ? (t)((v)*(m)) : (t)0)
#define TIFFmax(A,B) ((A)>(B)?(A):(B)) #define TIFFmax(A,B) ((A)>(B)?(A):(B))
@ -368,12 +384,16 @@ extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
extern uint32 _TIFFMultiply32(TIFF*, uint32, uint32, const char*); extern uint32 _TIFFMultiply32(TIFF*, uint32, uint32, const char*);
extern uint64 _TIFFMultiply64(TIFF*, uint64, uint64, const char*); extern uint64 _TIFFMultiply64(TIFF*, uint64, uint64, const char*);
extern tmsize_t _TIFFMultiplySSize(TIFF*, tmsize_t, tmsize_t, const char*);
extern tmsize_t _TIFFCastUInt64ToSSize(TIFF*, uint64, const char*);
extern void* _TIFFCheckMalloc(TIFF*, tmsize_t, tmsize_t, const char*); extern void* _TIFFCheckMalloc(TIFF*, tmsize_t, tmsize_t, const char*);
extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*); extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*);
extern double _TIFFUInt64ToDouble(uint64); extern double _TIFFUInt64ToDouble(uint64);
extern float _TIFFUInt64ToFloat(uint64); extern float _TIFFUInt64ToFloat(uint64);
extern float _TIFFClampDoubleToFloat(double);
extern tmsize_t extern tmsize_t
_TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip, _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip,
void **buf, tmsize_t bufsizetoalloc, void **buf, tmsize_t bufsizetoalloc,

View File

@ -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 * This define can be used in code that requires
* compilation-related definitions specific to a * compilation-related definitions specific to a
@ -6,4 +6,4 @@
* version checking should be done based on the * version checking should be done based on the
* string returned by TIFFGetVersion. * string returned by TIFFGetVersion.
*/ */
#define TIFFLIB_VERSION 20181110 #define TIFFLIB_VERSION 20191103

View File

@ -16,7 +16,11 @@ int _TIFF_vsnprintf_f(char* str, size_t size, const char* format, va_list ap)
int count = -1; int count = -1;
if (size != 0) if (size != 0)
#if _MSC_VER <= 1310
count = _vsnprintf(str, size, format, ap);
#else
count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); count = _vsnprintf_s(str, size, _TRUNCATE, format, ap);
#endif
if (count == -1) if (count == -1)
count = _vscprintf(format, ap); count = _vscprintf(format, ap);

View File

@ -6,7 +6,7 @@
"Description": "", "Description": "",
"Homepage": "http://www.simplesystems.org/libtiff/", "Homepage": "http://www.simplesystems.org/libtiff/",
"Version": "4.0.10", "Version": "4.1.0",
"License": "libtiff License", "License": "libtiff License",
"LicenseId": "libtiff", "LicenseId": "libtiff",
"LicenseFile": "COPYRIGHT", "LicenseFile": "COPYRIGHT",

View File

@ -136,7 +136,7 @@ SOURCES_FOR_NEON += \
android { android {
arm64-v8a|equals(QT_ARCH, arm64): SOURCES += $$SOURCES_FOR_NEON arm64-v8a | armeabi-v7a: SOURCES += $$SOURCES_FOR_NEON
} else: equals(QT_ARCH, arm)|equals(QT_ARCH, arm64) { } else: equals(QT_ARCH, arm)|equals(QT_ARCH, arm64) {
contains(QT_CPU_FEATURES.$$QT_ARCH, neon) { contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
# Default compiler settings include this feature, so just add to SOURCES # Default compiler settings include this feature, so just add to SOURCES

View File

@ -34,7 +34,8 @@
] ]
}, },
"sources": [ "sources": [
"-ljasper" { "type": "pkgConfig", "args": "jasper" },
{ "libs": "-ljasper" }
] ]
}, },
"mng": { "mng": {
@ -55,7 +56,8 @@
] ]
}, },
"sources": [ "sources": [
"-lmng" { "type": "pkgConfig", "args": "libmng" },
{ "libs": "-lmng" }
] ]
}, },
"tiff": { "tiff": {
@ -82,7 +84,8 @@
] ]
}, },
"sources": [ "sources": [
"-ltiff" { "type": "pkgConfig", "args": "libtiff-4" },
{ "libs": "-ltiff" }
] ]
}, },
"webp": { "webp": {
@ -112,7 +115,8 @@
] ]
}, },
"sources": [ "sources": [
"-lwebp -lwebpdemux -lwebpmux" { "type": "pkgConfig", "args": "libwebp libwebpmux libwebpdemux" },
{ "libs": "-lwebp -lwebpdemux -lwebpmux" }
] ]
} }
}, },
@ -136,7 +140,7 @@
"tiff": { "tiff": {
"label": "TIFF", "label": "TIFF",
"disable": "input.tiff == 'no'", "disable": "input.tiff == 'no'",
"condition": "features.imageformatplugin", "condition": "features.imageformatplugin && !(config.winrt && arch.i386)",
"output": [ "output": [
"privateFeature" "privateFeature"
] ]
@ -151,7 +155,7 @@
"webp": { "webp": {
"label": "WEBP", "label": "WEBP",
"disable": "input.webp == 'no'", "disable": "input.webp == 'no'",
"condition": "features.imageformatplugin", "condition": "features.imageformatplugin && !(config.winrt && arch.arm)",
"output": [ "output": [
"privateFeature" "privateFeature"
] ]

View File

@ -1382,13 +1382,6 @@ QDDSHandler::QDDSHandler() :
{ {
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QDDSHandler::name() const
{
return QByteArrayLiteral("dds");
}
#endif
bool QDDSHandler::canRead() const bool QDDSHandler::canRead() const
{ {
if (m_scanState == ScanNotScanned && !canRead(device())) if (m_scanState == ScanNotScanned && !canRead(device()))

View File

@ -53,10 +53,6 @@ class QDDSHandler : public QImageIOHandler
public: public:
QDDSHandler(); QDDSHandler();
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
bool canRead() const override; bool canRead() const override;
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const QImage &image) override; bool write(const QImage &image) override;

View File

@ -60,12 +60,12 @@ QImageIOPlugin::Capabilities QICNSPlugin::capabilities(QIODevice *device, const
{ {
if (format == QByteArrayLiteral("icns")) if (format == QByteArrayLiteral("icns"))
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device || !device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device || !device->isOpen())
return cap;
if (device->isReadable() && QICNSHandler::canRead(device)) if (device->isReadable() && QICNSHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
if (device->isWritable()) if (device->isWritable())

View File

@ -651,13 +651,6 @@ QICNSHandler::QICNSHandler() :
{ {
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QICNSHandler::name() const
{
return QByteArrayLiteral("icns");
}
#endif
bool QICNSHandler::canRead(QIODevice *device) bool QICNSHandler::canRead(QIODevice *device)
{ {
if (!device || !device->isReadable()) { if (!device || !device->isReadable()) {

View File

@ -132,10 +132,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const QImage &image) override; bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
bool supportsOption(ImageOption option) const override; bool supportsOption(ImageOption option) const override;
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

@ -21,9 +21,3 @@ qtConfig(jasper) {
} else:darwin: { } else:darwin: {
SUBDIRS += macjp2 SUBDIRS += macjp2
} }
winrt {
SUBDIRS -= tiff \
tga \
webp
}

View File

@ -64,12 +64,12 @@ QImageIOPlugin::Capabilities QJp2Plugin::capabilities(QIODevice *device, const Q
{ {
if (format == "jp2" || format == "j2k") if (format == "jp2" || format == "j2k")
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QJp2Handler::canRead(device, 0)) if (device->isReadable() && QJp2Handler::canRead(device, 0))
cap |= CanRead; cap |= CanRead;
if (device->isWritable()) if (device->isWritable())

View File

@ -308,17 +308,6 @@ bool QJp2Handler::supportsOption(ImageOption option) const
return (option == Quality || option == SubType); return (option == Quality || option == SubType);
} }
#if QT_DEPRECATED_SINCE(5, 13)
/*!
Return the common identifier of the format.
For JPEG 2000 this will return "jp2".
*/
QByteArray QJp2Handler::name() const
{
return QByteArrayLiteral("jp2");
}
#endif
/*! /*!
Automatic resource handling for a jas_image_t*. Automatic resource handling for a jas_image_t*.
*/ */

View File

@ -64,9 +64,6 @@ public:
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override; void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override; bool supportsOption(ImageOption option) const override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
private: private:
Q_DECLARE_PRIVATE(QJp2Handler) Q_DECLARE_PRIVATE(QJp2Handler)

View File

@ -58,16 +58,16 @@ QImageIOPlugin::Capabilities QMacHeifPlugin::capabilities(QIODevice *device, con
{ {
static const Capabilities sysCaps = QIIOFHelpers::systemCapabilities(QStringLiteral("public.heic")); static const Capabilities sysCaps = QIIOFHelpers::systemCapabilities(QStringLiteral("public.heic"));
Capabilities cap;
if (!sysCaps) if (!sysCaps)
return 0; return cap;
if (format == "heic" || format == "heif") if (format == "heic" || format == "heif")
return sysCaps; return sysCaps;
if (!format.isEmpty()) if (!format.isEmpty())
return 0; return cap;
if (!device->isOpen()) if (!device->isOpen())
return 0; return cap;
Capabilities cap;
if (sysCaps.testFlag(CanRead) && device->isReadable() && QMacHeifHandler::canRead(device)) if (sysCaps.testFlag(CanRead) && device->isReadable() && QMacHeifHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
if (sysCaps.testFlag(CanWrite) && device->isWritable()) if (sysCaps.testFlag(CanWrite) && device->isWritable())

View File

@ -57,12 +57,12 @@ QImageIOPlugin::Capabilities QMacJp2Plugin::capabilities(QIODevice *device, cons
{ {
if (format == "jp2") if (format == "jp2")
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QMacJp2Handler::canRead(device)) if (device->isReadable() && QMacJp2Handler::canRead(device))
cap |= CanRead; cap |= CanRead;
if (device->isWritable()) if (device->isWritable())

View File

@ -118,10 +118,4 @@ bool QMacJp2Handler::supportsOption(ImageOption option) const
return (option == Quality); return (option == Quality);
} }
QByteArray QMacJp2Handler::name() const
{
return QByteArrayLiteral("jp2");
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -63,7 +63,6 @@ public:
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override; void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(ImageOption option) const override; bool supportsOption(ImageOption option) const override;
QByteArray name() const override;
static bool canRead(QIODevice *iod); static bool canRead(QIODevice *iod);

View File

@ -66,12 +66,12 @@ QImageIOPlugin::Capabilities QMngPlugin::capabilities(QIODevice *device, const Q
{ {
if (format == "mng") if (format == "mng")
return Capabilities(CanRead); return Capabilities(CanRead);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QMngHandler::canRead(device)) if (device->isReadable() && QMngHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
return cap; return cap;

View File

@ -402,12 +402,6 @@ bool QMngHandler::canRead(QIODevice *device)
return device->peek(8) == "\x8A\x4D\x4E\x47\x0D\x0A\x1A\x0A"; return device->peek(8) == "\x8A\x4D\x4E\x47\x0D\x0A\x1A\x0A";
} }
/*! \reimp */
QByteArray QMngHandler::name() const
{
return "mng";
}
/*! \reimp */ /*! \reimp */
bool QMngHandler::read(QImage *image) bool QMngHandler::read(QImage *image)
{ {

View File

@ -57,7 +57,6 @@ class QMngHandler : public QImageIOHandler
QMngHandler(); QMngHandler();
~QMngHandler(); ~QMngHandler();
bool canRead() const override; bool canRead() const override;
QByteArray name() const override;
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const QImage &image) override; bool write(const QImage &image) override;
int currentImageNumber() const override; int currentImageNumber() const override;

View File

@ -64,12 +64,12 @@ QImageIOPlugin::Capabilities QTgaPlugin::capabilities(QIODevice *device, const Q
{ {
if (format == "tga") if (format == "tga")
return Capabilities(CanRead); return Capabilities(CanRead);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QTgaHandler::canRead(device)) if (device->isReadable() && QTgaHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
return cap; return cap;

View File

@ -98,13 +98,6 @@ bool QTgaHandler::read(QImage *image)
return !image->isNull(); return !image->isNull();
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QTgaHandler::name() const
{
return "tga";
}
#endif
QVariant QTgaHandler::option(ImageOption option) const QVariant QTgaHandler::option(ImageOption option) const
{ {
if (option == Size && canRead()) { if (option == Size && canRead()) {

View File

@ -55,10 +55,6 @@ public:
bool canRead() const override; bool canRead() const override;
bool read(QImage *image) override; bool read(QImage *image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

@ -60,12 +60,12 @@ QImageIOPlugin::Capabilities QTiffPlugin::capabilities(QIODevice *device, const
{ {
if (format == "tiff" || format == "tif") if (format == "tiff" || format == "tif")
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QTiffHandler::canRead(device)) if (device->isReadable() && QTiffHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
if (device->isWritable()) if (device->isWritable())

View File

@ -205,9 +205,14 @@ bool QTiffHandlerPrivate::canRead(QIODevice *device)
// current implementation uses TIFFClientOpen which needs to be // current implementation uses TIFFClientOpen which needs to be
// able to seek, so sequential devices are not supported // able to seek, so sequential devices are not supported
QByteArray header = device->peek(4); char h[4];
return header == QByteArray::fromRawData("\x49\x49\x2A\x00", 4) if (device->peek(h, 4) != 4)
|| header == QByteArray::fromRawData("\x4D\x4D\x00\x2A", 4); return false;
if ((h[0] == 0x49 && h[1] == 0x49) && (h[2] == 0x2a || h[2] == 0x2b) && h[3] == 0)
return true; // Little endian, classic or bigtiff
if ((h[0] == 0x4d && h[1] == 0x4d) && h[2] == 0 && (h[3] == 0x2a || h[3] == 0x2b))
return true; // Big endian, classic or bigtiff
return false;
} }
bool QTiffHandlerPrivate::openForRead(QIODevice *device) bool QTiffHandlerPrivate::openForRead(QIODevice *device)
@ -278,7 +283,7 @@ bool QTiffHandlerPrivate::readHeaders(QIODevice *device)
else if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1) else if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8 && samplesPerPixel == 1)
format = QImage::Format_Indexed8; format = QImage::Format_Indexed8;
else if (samplesPerPixel < 4) else if (samplesPerPixel < 4)
if (bitPerSample > 8 && photometric == PHOTOMETRIC_RGB) if (bitPerSample == 16 && photometric == PHOTOMETRIC_RGB)
format = QImage::Format_RGBX64; format = QImage::Format_RGBX64;
else else
format = QImage::Format_RGB32; format = QImage::Format_RGB32;
@ -294,7 +299,7 @@ bool QTiffHandlerPrivate::readHeaders(QIODevice *device)
if (!gotField || !count || extrasamples[0] == EXTRASAMPLE_UNSPECIFIED) if (!gotField || !count || extrasamples[0] == EXTRASAMPLE_UNSPECIFIED)
premultiplied = false; premultiplied = false;
if (bitPerSample > 8 && photometric == PHOTOMETRIC_RGB) { if (bitPerSample == 16 && photometric == PHOTOMETRIC_RGB) {
// We read 64-bit raw, so unassoc remains unpremultiplied. // We read 64-bit raw, so unassoc remains unpremultiplied.
if (gotField && count && extrasamples[0] == EXTRASAMPLE_UNASSALPHA) if (gotField && count && extrasamples[0] == EXTRASAMPLE_UNASSALPHA)
premultiplied = false; premultiplied = false;
@ -394,9 +399,10 @@ bool QTiffHandler::read(QImage *image)
} }
for (int i = 0; i<tableSize ;++i) { for (int i = 0; i<tableSize ;++i) {
const int red = redTable[i] / 257; // emulate libtiff behavior for 16->8 bit color map conversion: just ignore the lower 8 bits
const int green = greenTable[i] / 257; const int red = redTable[i] >> 8;
const int blue = blueTable[i] / 257; const int green = greenTable[i] >> 8;
const int blue = blueTable[i] >> 8;
qtColorTable[i] = qRgb(red, green, blue); qtColorTable[i] = qRgb(red, green, blue);
} }
} }
@ -810,13 +816,6 @@ bool QTiffHandler::write(const QImage &image)
return true; return true;
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QTiffHandler::name() const
{
return "tiff";
}
#endif
QVariant QTiffHandler::option(ImageOption option) const QVariant QTiffHandler::option(ImageOption option) const
{ {
if (option == Size && canRead()) { if (option == Size && canRead()) {

View File

@ -55,10 +55,6 @@ public:
bool read(QImage *image) override; bool read(QImage *image) override;
bool write(const QImage &image) override; bool write(const QImage &image) override;
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
static bool canRead(QIODevice *device); static bool canRead(QIODevice *device);
QVariant option(ImageOption option) const override; QVariant option(ImageOption option) const override;

View File

@ -64,13 +64,13 @@ QImageIOPlugin::Capabilities QWbmpPlugin::capabilities(QIODevice *device, const
if (format == "wbmp") if (format == "wbmp")
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
Capabilities cap;
if (!format.isEmpty()) if (!format.isEmpty())
return 0; return cap;
if (!device->isOpen()) if (!device->isOpen())
return 0; return cap;
Capabilities cap;
if (device->isReadable() && QWbmpHandler::canRead(device)) if (device->isReadable() && QWbmpHandler::canRead(device))
cap |= CanRead; cap |= CanRead;

View File

@ -64,12 +64,12 @@ QWebpPlugin::Capabilities QWebpPlugin::capabilities(QIODevice *device, const QBy
if (format == "webp") if (format == "webp")
return Capabilities(CanRead | CanWrite); return Capabilities(CanRead | CanWrite);
if (!format.isEmpty())
return 0;
if (!device->isOpen())
return 0;
Capabilities cap; Capabilities cap;
if (!format.isEmpty())
return cap;
if (!device->isOpen())
return cap;
if (device->isReadable() && QWebpHandler::canRead(device)) if (device->isReadable() && QWebpHandler::canRead(device))
cap |= CanRead; cap |= CanRead;
if (device->isWritable()) if (device->isWritable())

View File

@ -162,6 +162,7 @@ bool QWebpHandler::read(QImage *image)
if (!ensureScanned() || device()->isSequential() || !ensureDemuxer()) if (!ensureScanned() || device()->isSequential() || !ensureDemuxer())
return false; return false;
QRect prevFrameRect;
if (m_iter.frame_num == 0) { if (m_iter.frame_num == 0) {
// Read global meta-data chunks first // Read global meta-data chunks first
WebPChunkIterator metaDataIter; WebPChunkIterator metaDataIter;
@ -177,6 +178,9 @@ bool QWebpHandler::read(QImage *image)
if (!WebPDemuxGetFrame(m_demuxer, 1, &m_iter)) if (!WebPDemuxGetFrame(m_demuxer, 1, &m_iter))
return false; return false;
} else { } else {
if (m_iter.has_alpha && m_iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND)
prevFrameRect = currentImageRect();
// Go to next frame // Go to next frame
if (!WebPDemuxNextFrame(&m_iter)) if (!WebPDemuxNextFrame(&m_iter))
return false; return false;
@ -208,8 +212,16 @@ bool QWebpHandler::read(QImage *image)
} else { } else {
// Animation // Animation
QPainter painter(m_composited); QPainter painter(m_composited);
if (m_features.has_alpha && m_iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) if (!prevFrameRect.isEmpty()) {
m_composited->fill(Qt::transparent); painter.setCompositionMode(QPainter::CompositionMode_Clear);
painter.fillRect(prevFrameRect, Qt::black);
}
if (m_features.has_alpha) {
if (m_iter.blend_method == WEBP_MUX_NO_BLEND)
painter.setCompositionMode(QPainter::CompositionMode_Source);
else
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
}
painter.drawImage(currentImageRect(), frame); painter.drawImage(currentImageRect(), frame);
*image = *m_composited; *image = *m_composited;
@ -367,13 +379,6 @@ bool QWebpHandler::supportsOption(ImageOption option) const
|| option == BackgroundColor; || option == BackgroundColor;
} }
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray QWebpHandler::name() const
{
return QByteArrayLiteral("webp");
}
#endif
int QWebpHandler::imageCount() const int QWebpHandler::imageCount() const
{ {
if (!ensureScanned()) if (!ensureScanned())

View File

@ -57,10 +57,6 @@ public:
~QWebpHandler(); ~QWebpHandler();
public: public:
#if QT_DEPRECATED_SINCE(5, 13)
QByteArray name() const override;
#endif
bool canRead() const override; bool canRead() const override;
bool read(QImage *image) override; bool read(QImage *image) override;

View File

@ -90,6 +90,9 @@ private slots:
void colorSpace_data(); void colorSpace_data();
void colorSpace(); void colorSpace();
void bigtiff_data();
void bigtiff();
private: private:
QString prefix; QString prefix;
}; };
@ -173,6 +176,10 @@ void tst_qtiff::readImage_data()
QTest::newRow("tiled_oddsize_mono") << QString("tiled_oddsize_mono.tiff") << QSize(59, 71); QTest::newRow("tiled_oddsize_mono") << QString("tiled_oddsize_mono.tiff") << QSize(59, 71);
QTest::newRow("16bpc") << QString("16bpc.tiff") << QSize(64, 46); QTest::newRow("16bpc") << QString("16bpc.tiff") << QSize(64, 46);
QTest::newRow("gray16") << QString("gray16.tiff") << QSize(64, 46); QTest::newRow("gray16") << QString("gray16.tiff") << QSize(64, 46);
QTest::newRow("big_rgb") << QString("big_rgb.tiff") << QSize(64, 64);
QTest::newRow("big_rgb_bigendian") << QString("big_rgb_bigendian.tiff") << QSize(64, 64);
QTest::newRow("big_grayscale") << QString("big_grayscale.tiff") << QSize(64, 64);
QTest::newRow("big_16bpc") << QString("big_16bpc.tiff") << QSize(64, 46);
} }
void tst_qtiff::readImage() void tst_qtiff::readImage()
@ -662,5 +669,27 @@ void tst_qtiff::colorSpace()
QCOMPARE(image2, image); QCOMPARE(image2, image);
} }
void tst_qtiff::bigtiff_data()
{
QTest::addColumn<QString>("expectedFile");
QTest::addColumn<QString>("bigtiffFile");
QTest::newRow("big_rgb") << QString("original_rgb.tiff") << QString("big_rgb.tiff");
QTest::newRow("big_rgb_bigendian") << QString("original_rgb.tiff") << QString("big_rgb_bigendian.tiff");
QTest::newRow("big_grayscale") << QString("original_grayscale.tiff") << QString("big_grayscale.tiff");
QTest::newRow("big_16bpc") << QString("16bpc.tiff") << QString("big_16bpc.tiff");
}
void tst_qtiff::bigtiff()
{
QFETCH(QString, expectedFile);
QFETCH(QString, bigtiffFile);
QImage expectedImage(prefix + expectedFile);
QImage bigtiffImage(prefix + bigtiffFile);
QVERIFY(!bigtiffImage.isNull());
QCOMPARE(expectedImage, bigtiffImage);
}
QTEST_MAIN(tst_qtiff) QTEST_MAIN(tst_qtiff)
#include "tst_qtiff.moc" #include "tst_qtiff.moc"

View File

@ -52,5 +52,9 @@
<file>tiff/oddsize_mono.tiff</file> <file>tiff/oddsize_mono.tiff</file>
<file>tiff/tiled_rgb.tiff</file> <file>tiff/tiled_rgb.tiff</file>
<file>tiff/gray16.tiff</file> <file>tiff/gray16.tiff</file>
<file>tiff/big_rgb.tiff</file>
<file>tiff/big_16bpc.tiff</file>
<file>tiff/big_grayscale.tiff</file>
<file>tiff/big_rgb_bigendian.tiff</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.