2010-05-12 01:44:00 +08:00
/*
* Copyright ( c ) 1988 - 1997 Sam Leffler
* Copyright ( c ) 1991 - 1997 Silicon Graphics , Inc .
*
2012-02-29 23:01:28 +08:00
* Permission to use , copy , modify , distribute , and sell this software and
2010-05-12 01:44:00 +08:00
* its documentation for any purpose is hereby granted without fee , provided
* that ( i ) the above copyright notices and this permission notice appear in
* all copies of the software and related documentation , and ( ii ) the names of
* Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific , prior written
* permission of Sam Leffler and Silicon Graphics .
2012-02-29 23:01:28 +08:00
*
* THE SOFTWARE IS PROVIDED " AS-IS " AND WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS , IMPLIED OR OTHERWISE , INCLUDING WITHOUT LIMITATION , ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE .
*
2010-05-12 01:44:00 +08:00
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
* ANY SPECIAL , INCIDENTAL , INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND ,
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS ,
2012-02-29 23:01:28 +08:00
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE , AND ON ANY THEORY OF
* LIABILITY , ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2010-05-12 01:44:00 +08:00
* OF THIS SOFTWARE .
*/
/*
* TIFF Library .
*
* Directory Read Support Routines .
*/
2012-02-29 23:01:28 +08:00
/* Suggested pending improvements:
* - add a field ' field_info ' to the TIFFDirEntry structure , and set that with
* the pointer to the appropriate TIFFField structure early on in
* TIFFReadDirectory , so as to eliminate current possibly repetitive lookup .
*/
2010-05-12 01:44:00 +08:00
# include "tiffiop.h"
2017-12-08 20:47:54 +08:00
# include <float.h>
# include <stdlib.h>
2010-05-12 01:44:00 +08:00
2012-02-29 23:01:28 +08:00
# define FAILED_FII ((uint32) -1)
2010-05-12 01:44:00 +08:00
2021-03-02 07:17:30 +08:00
/*
* Largest 64 - bit signed integer value .
*/
# define TIFF_INT64_MAX ((int64)(TIFF_UINT64_MAX >> 1))
2010-07-16 20:54:53 +08:00
# ifdef HAVE_IEEEFP
2012-02-29 23:01:28 +08:00
# define TIFFCvtIEEEFloatToNative(tif, n, fp)
# define TIFFCvtIEEEDoubleToNative(tif, n, dp)
# else
extern void TIFFCvtIEEEFloatToNative ( TIFF * , uint32 , float * ) ;
extern void TIFFCvtIEEEDoubleToNative ( TIFF * , uint32 , double * ) ;
# endif
enum TIFFReadDirEntryErr {
2017-12-08 20:47:54 +08:00
TIFFReadDirEntryErrOk = 0 ,
TIFFReadDirEntryErrCount = 1 ,
TIFFReadDirEntryErrType = 2 ,
TIFFReadDirEntryErrIo = 3 ,
TIFFReadDirEntryErrRange = 4 ,
TIFFReadDirEntryErrPsdif = 5 ,
TIFFReadDirEntryErrSizesan = 6 ,
TIFFReadDirEntryErrAlloc = 7 ,
2012-02-29 23:01:28 +08:00
} ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryByte ( TIFF * tif , TIFFDirEntry * direntry , uint8 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong ( TIFF * tif , TIFFDirEntry * direntry , uint32 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat ( TIFF * tif , TIFFDirEntry * direntry , float * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryArray ( TIFF * tif , TIFFDirEntry * direntry , uint32 * count , uint32 desttypesize , void * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray ( TIFF * tif , TIFFDirEntry * direntry , uint8 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyteArray ( TIFF * tif , TIFFDirEntry * direntry , int8 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryShortArray ( TIFF * tif , TIFFDirEntry * direntry , uint16 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntrySshortArray ( TIFF * tif , TIFFDirEntry * direntry , int16 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryLongArray ( TIFF * tif , TIFFDirEntry * direntry , uint32 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray ( TIFF * tif , TIFFDirEntry * direntry , int32 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array ( TIFF * tif , TIFFDirEntry * direntry , uint64 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array ( TIFF * tif , TIFFDirEntry * direntry , int64 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray ( TIFF * tif , TIFFDirEntry * direntry , float * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryDoubleArray ( TIFF * tif , TIFFDirEntry * direntry , double * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array ( TIFF * tif , TIFFDirEntry * direntry , uint64 * * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value ) ;
#if 0
static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value ) ;
# endif
static void TIFFReadDirEntryCheckedByte ( TIFF * tif , TIFFDirEntry * direntry , uint8 * value ) ;
static void TIFFReadDirEntryCheckedSbyte ( TIFF * tif , TIFFDirEntry * direntry , int8 * value ) ;
static void TIFFReadDirEntryCheckedShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value ) ;
static void TIFFReadDirEntryCheckedSshort ( TIFF * tif , TIFFDirEntry * direntry , int16 * value ) ;
static void TIFFReadDirEntryCheckedLong ( TIFF * tif , TIFFDirEntry * direntry , uint32 * value ) ;
static void TIFFReadDirEntryCheckedSlong ( TIFF * tif , TIFFDirEntry * direntry , int32 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedLong8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSlong8 ( TIFF * tif , TIFFDirEntry * direntry , int64 * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational ( TIFF * tif , TIFFDirEntry * direntry , double * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational ( TIFF * tif , TIFFDirEntry * direntry , double * value ) ;
static void TIFFReadDirEntryCheckedFloat ( TIFF * tif , TIFFDirEntry * direntry , float * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSbyte ( int8 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteShort ( uint16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSshort ( int16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong ( uint32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteByte ( uint8 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteShort ( uint16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSshort ( int16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong ( uint32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSbyte ( int8 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSshort ( int16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong ( uint32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortShort ( uint16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong ( uint32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSbyte ( int8 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSshort ( int16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong ( uint32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongLong8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlongSlong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sbyte ( int8 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Sshort ( int16 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong ( int32 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLong8Slong8 ( int64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSlong8Long8 ( uint64 value ) ;
static enum TIFFReadDirEntryErr TIFFReadDirEntryData ( TIFF * tif , uint64 offset , tmsize_t size , void * dest ) ;
static void TIFFReadDirEntryOutputErr ( TIFF * tif , enum TIFFReadDirEntryErr err , const char * module , const char * tagname , int recover ) ;
static void TIFFReadDirectoryCheckOrder ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount ) ;
static TIFFDirEntry * TIFFReadDirectoryFindEntry ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount , uint16 tagid ) ;
static void TIFFReadDirectoryFindFieldInfo ( TIFF * tif , uint16 tagid , uint32 * fii ) ;
static int EstimateStripByteCounts ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount ) ;
static void MissingRequired ( TIFF * , const char * ) ;
static int TIFFCheckDirOffset ( TIFF * tif , uint64 diroff ) ;
static int CheckDirCount ( TIFF * , TIFFDirEntry * , uint32 ) ;
static uint16 TIFFFetchDirectory ( TIFF * tif , uint64 diroff , TIFFDirEntry * * pdir , uint64 * nextdiroff ) ;
static int TIFFFetchNormalTag ( TIFF * , TIFFDirEntry * , int recover ) ;
static int TIFFFetchStripThing ( TIFF * tif , TIFFDirEntry * dir , uint32 nstrips , uint64 * * lpp ) ;
static int TIFFFetchSubjectDistance ( TIFF * , TIFFDirEntry * ) ;
static void ChopUpSingleUncompressedStrip ( TIFF * ) ;
2020-03-24 02:43:45 +08:00
static void TryChopUpUncompressedBigTiff ( TIFF * ) ;
2012-02-29 23:01:28 +08:00
static uint64 TIFFReadUInt64 ( const uint8 * value ) ;
2019-02-12 21:43:58 +08:00
static int _TIFFGetMaxColorChannels ( uint16 photometric ) ;
2012-02-29 23:01:28 +08:00
2017-12-08 20:47:54 +08:00
static int _TIFFFillStrilesInternal ( TIFF * tif , int loadStripByteCount ) ;
2012-02-29 23:01:28 +08:00
typedef union _UInt64Aligned_t
{
double d ;
2017-12-08 20:47:54 +08:00
uint64 l ;
uint32 i [ 2 ] ;
uint16 s [ 4 ] ;
uint8 c [ 8 ] ;
2012-02-29 23:01:28 +08:00
} UInt64Aligned_t ;
/*
Unaligned safe copy of a uint64 value from an octet array .
*/
static uint64 TIFFReadUInt64 ( const uint8 * value )
{
2017-12-08 20:47:54 +08:00
UInt64Aligned_t result ;
result . c [ 0 ] = value [ 0 ] ;
result . c [ 1 ] = value [ 1 ] ;
result . c [ 2 ] = value [ 2 ] ;
result . c [ 3 ] = value [ 3 ] ;
result . c [ 4 ] = value [ 4 ] ;
result . c [ 5 ] = value [ 5 ] ;
result . c [ 6 ] = value [ 6 ] ;
result . c [ 7 ] = value [ 7 ] ;
return result . l ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryByte ( TIFF * tif , TIFFDirEntry * direntry , uint8 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
2021-03-02 07:17:30 +08:00
case TIFF_UNDEFINED : /* Support to read TIFF_UNDEFINED with field_readcount==1 */
2017-12-08 20:47:54 +08:00
TIFFReadDirEntryCheckedByte ( tif , direntry , value ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeByteSbyte ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
{
uint16 m ;
TIFFReadDirEntryCheckedShort ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeByteShort ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeByteSshort ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeByteLong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeByteSlong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
{
uint64 m ;
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeByteLong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeByteSlong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint8 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 m ;
TIFFReadDirEntryCheckedByte ( tif , direntry , & m ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeShortSbyte ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
TIFFReadDirEntryCheckedShort ( tif , direntry , value ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeShortSshort ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeShortLong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeShortSlong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
{
uint64 m ;
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeShortLong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeShortSlong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint16 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong ( TIFF * tif , TIFFDirEntry * direntry , uint32 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 m ;
TIFFReadDirEntryCheckedByte ( tif , direntry , & m ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLongSbyte ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
{
uint16 m ;
TIFFReadDirEntryCheckedShort ( tif , direntry , & m ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLongSshort ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
TIFFReadDirEntryCheckedLong ( tif , direntry , value ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLongSlong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
{
uint64 m ;
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeLongLong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeLongSlong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint32 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 m ;
TIFFReadDirEntryCheckedByte ( tif , direntry , & m ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLong8Sbyte ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
{
uint16 m ;
TIFFReadDirEntryCheckedShort ( tif , direntry , & m ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLong8Sshort ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
err = TIFFReadDirEntryCheckRangeLong8Slong ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , value ) ;
return ( err ) ;
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
err = TIFFReadDirEntryCheckRangeLong8Slong8 ( m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloat ( TIFF * tif , TIFFDirEntry * direntry , float * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 m ;
TIFFReadDirEntryCheckedByte ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
{
uint16 m ;
TIFFReadDirEntryCheckedShort ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
{
uint64 m ;
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
2012-02-29 23:01:28 +08:00
# if defined(__WIN32__) && (_MSC_VER < 1500)
2017-12-08 20:47:54 +08:00
/*
* XXX : MSVC 6.0 does not support conversion
* of 64 - bit integers into floating point
* values .
*/
* value = _TIFFUInt64ToFloat ( m ) ;
2012-02-29 23:01:28 +08:00
# else
2017-12-08 20:47:54 +08:00
* value = ( float ) m ;
2012-02-29 23:01:28 +08:00
# endif
2017-12-08 20:47:54 +08:00
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_RATIONAL :
{
double m ;
err = TIFFReadDirEntryCheckedRational ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SRATIONAL :
{
double m ;
err = TIFFReadDirEntryCheckedSrational ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_FLOAT :
TIFFReadDirEntryCheckedFloat ( tif , direntry , value ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_DOUBLE :
{
double m ;
err = TIFFReadDirEntryCheckedDouble ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
2021-03-02 07:17:30 +08:00
if ( ( m > FLT_MAX ) | | ( m < - FLT_MAX ) )
2017-12-08 20:47:54 +08:00
return ( TIFFReadDirEntryErrRange ) ;
* value = ( float ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 m ;
TIFFReadDirEntryCheckedByte ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
{
int8 m ;
TIFFReadDirEntryCheckedSbyte ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SHORT :
{
uint16 m ;
TIFFReadDirEntryCheckedShort ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
{
int16 m ;
TIFFReadDirEntryCheckedSshort ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
{
int32 m ;
TIFFReadDirEntryCheckedSlong ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
{
uint64 m ;
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
2012-02-29 23:01:28 +08:00
# if defined(__WIN32__) && (_MSC_VER < 1500)
2017-12-08 20:47:54 +08:00
/*
* XXX : MSVC 6.0 does not support conversion
* of 64 - bit integers into floating point
* values .
*/
* value = _TIFFUInt64ToDouble ( m ) ;
2010-05-12 01:44:00 +08:00
# else
2017-12-08 20:47:54 +08:00
* value = ( double ) m ;
2010-05-12 01:44:00 +08:00
# endif
2017-12-08 20:47:54 +08:00
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
{
int64 m ;
err = TIFFReadDirEntryCheckedSlong8 ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_RATIONAL :
err = TIFFReadDirEntryCheckedRational ( tif , direntry , value ) ;
return ( err ) ;
case TIFF_SRATIONAL :
err = TIFFReadDirEntryCheckedSrational ( tif , direntry , value ) ;
return ( err ) ;
case TIFF_FLOAT :
{
float m ;
TIFFReadDirEntryCheckedFloat ( tif , direntry , & m ) ;
* value = ( double ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_DOUBLE :
err = TIFFReadDirEntryCheckedDouble ( tif , direntry , value ) ;
return ( err ) ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
if ( direntry - > tdir_count ! = 1 )
return ( TIFFReadDirEntryErrCount ) ;
switch ( direntry - > tdir_type )
{
case TIFF_LONG :
case TIFF_IFD :
{
uint32 m ;
TIFFReadDirEntryCheckedLong ( tif , direntry , & m ) ;
* value = ( uint64 ) m ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_LONG8 :
case TIFF_IFD8 :
err = TIFFReadDirEntryCheckedLong8 ( tif , direntry , value ) ;
return ( err ) ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
# define INITIAL_THRESHOLD (1024 * 1024)
# define THRESHOLD_MULTIPLIER 10
# define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD)
static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc (
TIFF * tif , uint64 offset , tmsize_t size , void * * pdest )
2012-02-29 23:01:28 +08:00
{
2019-02-12 21:43:58 +08:00
# if SIZEOF_SIZE_T == 8
2017-12-08 20:47:54 +08:00
tmsize_t threshold = INITIAL_THRESHOLD ;
# endif
tmsize_t already_read = 0 ;
2012-02-29 23:01:28 +08:00
2017-12-08 20:47:54 +08:00
assert ( ! isMapped ( tif ) ) ;
if ( ! SeekOK ( tif , offset ) )
return ( TIFFReadDirEntryErrIo ) ;
/* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */
/* so as to avoid allocating too much memory in case the file is too */
/* short. We could ask for the file size, but this might be */
/* expensive with some I/O layers (think of reading a gzipped file) */
/* Restrict to 64 bit processes, so as to avoid reallocs() */
/* on 32 bit processes where virtual memory is scarce. */
while ( already_read < size )
2012-10-17 15:12:04 +08:00
{
2017-12-08 20:47:54 +08:00
void * new_dest ;
tmsize_t bytes_read ;
tmsize_t to_read = size - already_read ;
2019-02-12 21:43:58 +08:00
# if SIZEOF_SIZE_T == 8
2017-12-08 20:47:54 +08:00
if ( to_read > = threshold & & threshold < MAX_THRESHOLD )
2012-10-17 15:12:04 +08:00
{
2017-12-08 20:47:54 +08:00
to_read = threshold ;
threshold * = THRESHOLD_MULTIPLIER ;
2012-10-17 15:12:04 +08:00
}
2017-12-08 20:47:54 +08:00
# endif
2010-05-12 01:44:00 +08:00
2017-12-08 20:47:54 +08:00
new_dest = ( uint8 * ) _TIFFrealloc (
* pdest , already_read + to_read ) ;
if ( new_dest = = NULL )
2012-10-17 15:12:04 +08:00
{
2017-12-08 20:47:54 +08:00
TIFFErrorExt ( tif - > tif_clientdata , tif - > tif_name ,
" Failed to allocate memory for %s "
" (%ld elements of %ld bytes each) " ,
" TIFFReadDirEntryArray " ,
( long ) 1 , ( long ) ( already_read + to_read ) ) ;
return TIFFReadDirEntryErrAlloc ;
2012-10-17 15:12:04 +08:00
}
2017-12-08 20:47:54 +08:00
* pdest = new_dest ;
bytes_read = TIFFReadFile ( tif ,
( char * ) * pdest + already_read , to_read ) ;
already_read + = bytes_read ;
if ( bytes_read ! = to_read ) {
return TIFFReadDirEntryErrIo ;
2012-10-17 15:12:04 +08:00
}
2017-12-08 20:47:54 +08:00
}
return TIFFReadDirEntryErrOk ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntryArrayWithLimit (
TIFF * tif , TIFFDirEntry * direntry , uint32 * count , uint32 desttypesize ,
void * * value , uint64 maxcount )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
int typesize ;
uint32 datasize ;
void * data ;
uint64 target_count64 ;
2021-03-02 07:17:30 +08:00
int original_datasize_clamped ;
2017-12-08 20:47:54 +08:00
typesize = TIFFDataWidth ( direntry - > tdir_type ) ;
target_count64 = ( direntry - > tdir_count > maxcount ) ?
maxcount : direntry - > tdir_count ;
if ( ( target_count64 = = 0 ) | | ( typesize = = 0 ) )
{
* value = 0 ;
return ( TIFFReadDirEntryErrOk ) ;
}
( void ) desttypesize ;
2021-03-02 07:17:30 +08:00
/* We just want to know if the original tag size is more than 4 bytes
* ( classic TIFF ) or 8 bytes ( BigTIFF )
*/
original_datasize_clamped =
( ( direntry - > tdir_count > 10 ) ? 10 : ( int ) direntry - > tdir_count ) * typesize ;
2017-12-08 20:47:54 +08:00
/*
* As a sanity check , make sure we have no more than a 2 GB tag array
* in either the current data type or the dest data type . This also
* avoids problems with overflow of tmsize_t on 32 bit systems .
*/
if ( ( uint64 ) ( 2147483647 / typesize ) < target_count64 )
return ( TIFFReadDirEntryErrSizesan ) ;
if ( ( uint64 ) ( 2147483647 / desttypesize ) < target_count64 )
return ( TIFFReadDirEntryErrSizesan ) ;
* count = ( uint32 ) target_count64 ;
datasize = ( * count ) * typesize ;
assert ( ( tmsize_t ) datasize > 0 ) ;
2021-03-02 07:17:30 +08:00
if ( isMapped ( tif ) & & datasize > ( uint64 ) tif - > tif_size )
2017-12-08 20:47:54 +08:00
return TIFFReadDirEntryErrIo ;
if ( ! isMapped ( tif ) & &
( ( ( tif - > tif_flags & TIFF_BIGTIFF ) & & datasize > 8 ) | |
( ! ( tif - > tif_flags & TIFF_BIGTIFF ) & & datasize > 4 ) ) )
{
data = NULL ;
}
else
{
data = _TIFFCheckMalloc ( tif , * count , typesize , " ReadDirEntryArray " ) ;
if ( data = = 0 )
return ( TIFFReadDirEntryErrAlloc ) ;
}
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
2021-03-02 07:17:30 +08:00
if ( original_datasize_clamped < = 4 )
2017-12-08 20:47:54 +08:00
_TIFFmemcpy ( data , & direntry - > tdir_offset , datasize ) ;
else
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
if ( isMapped ( tif ) )
err = TIFFReadDirEntryData ( tif , ( uint64 ) offset , ( tmsize_t ) datasize , data ) ;
else
err = TIFFReadDirEntryDataAndRealloc ( tif , ( uint64 ) offset , ( tmsize_t ) datasize , & data ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
}
}
else
{
2021-03-02 07:17:30 +08:00
if ( original_datasize_clamped < = 8 )
2017-12-08 20:47:54 +08:00
_TIFFmemcpy ( data , & direntry - > tdir_offset , datasize ) ;
else
{
enum TIFFReadDirEntryErr err ;
uint64 offset = direntry - > tdir_offset . toff_long8 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( & offset ) ;
if ( isMapped ( tif ) )
err = TIFFReadDirEntryData ( tif , ( uint64 ) offset , ( tmsize_t ) datasize , data ) ;
else
err = TIFFReadDirEntryDataAndRealloc ( tif , ( uint64 ) offset , ( tmsize_t ) datasize , & data ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
}
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntryArray ( TIFF * tif , TIFFDirEntry * direntry , uint32 * count , uint32 desttypesize , void * * value )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
return TIFFReadDirEntryArrayWithLimit ( tif , direntry , count ,
desttypesize , value , ~ ( ( uint64 ) 0 ) ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntryByteArray ( TIFF * tif , TIFFDirEntry * direntry , uint8 * * value )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
uint8 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_ASCII :
case TIFF_UNDEFINED :
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 1 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_ASCII :
case TIFF_UNDEFINED :
case TIFF_BYTE :
* value = ( uint8 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SBYTE :
{
int8 * m ;
uint32 n ;
m = ( int8 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
err = TIFFReadDirEntryCheckRangeByteSbyte ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( uint8 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
}
data = ( uint8 * ) _TIFFmalloc ( count ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_SHORT :
{
uint16 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
err = TIFFReadDirEntryCheckRangeByteShort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeByteSshort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
err = TIFFReadDirEntryCheckRangeByteLong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeByteSlong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeByteLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
uint8 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeByteSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint8 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntrySbyteArray ( TIFF * tif , TIFFDirEntry * direntry , int8 * * value )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
int8 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_UNDEFINED :
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 1 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_UNDEFINED :
case TIFF_BYTE :
{
uint8 * m ;
uint32 n ;
m = ( uint8 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
err = TIFFReadDirEntryCheckRangeSbyteByte ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( int8 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SBYTE :
* value = ( int8 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( int8 * ) _TIFFmalloc ( count ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_SHORT :
{
uint16 * ma ;
int8 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteShort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
int8 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteSshort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
int8 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteLong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
int8 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteSlong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
int8 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
int8 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSbyteSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int8 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntryShortArray ( TIFF * tif , TIFFDirEntry * direntry , uint16 * * value )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
uint16 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 2 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_SHORT :
* value = ( uint16 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfShort ( * value , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SSHORT :
{
int16 * m ;
uint32 n ;
m = ( int16 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) m ) ;
err = TIFFReadDirEntryCheckRangeShortSshort ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( uint16 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
}
data = ( uint16 * ) _TIFFmalloc ( count * 2 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( uint16 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
err = TIFFReadDirEntryCheckRangeShortSbyte ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
err = TIFFReadDirEntryCheckRangeShortLong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeShortSlong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeShortLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
uint16 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeShortSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint16 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntrySshortArray ( TIFF * tif , TIFFDirEntry * direntry , int16 * * value )
2012-02-29 23:01:28 +08:00
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
int16 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 2 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_SHORT :
{
uint16 * m ;
uint32 n ;
m = ( uint16 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( m ) ;
err = TIFFReadDirEntryCheckRangeSshortShort ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( int16 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SSHORT :
* value = ( int16 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfShort ( ( uint16 * ) ( * value ) , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( int16 * ) _TIFFmalloc ( count * 2 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
int16 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int16 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
int16 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int16 ) ( * ma + + ) ;
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
int16 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
err = TIFFReadDirEntryCheckRangeSshortLong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
int16 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSshortSlong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
int16 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeSshortLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int16 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
int16 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSshortSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int16 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
static enum TIFFReadDirEntryErr TIFFReadDirEntryLongArray ( TIFF * tif , TIFFDirEntry * direntry , uint32 * * value )
{
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
uint32 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 4 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG :
* value = ( uint32 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( * value , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SLONG :
{
int32 * m ;
uint32 n ;
m = ( int32 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) m ) ;
err = TIFFReadDirEntryCheckRangeLongSlong ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( uint32 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
}
data = ( uint32 * ) _TIFFmalloc ( count * 4 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( uint32 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
err = TIFFReadDirEntryCheckRangeLongSbyte ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( uint32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeLongSshort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeLongLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
uint32 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeLongSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint32 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
}
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlongArray ( TIFF * tif , TIFFDirEntry * direntry , int32 * * value )
{
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
int32 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 4 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG :
{
uint32 * m ;
uint32 n ;
m = ( uint32 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) m ) ;
err = TIFFReadDirEntryCheckRangeSlongLong ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( int32 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG :
* value = ( int32 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( ( uint32 * ) ( * value ) , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( int32 * ) _TIFFmalloc ( count * 4 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
int32 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int32 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
int32 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int32 ) ( * ma + + ) ;
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
int32 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( int32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
int32 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
* mb + + = ( int32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
int32 * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
err = TIFFReadDirEntryCheckRangeSlongLong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int32 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
int32 * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeSlongSlong8 ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( int32 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8ArrayWithLimit (
TIFF * tif , TIFFDirEntry * direntry , uint64 * * value , uint64 maxcount )
{
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
uint64 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArrayWithLimit ( tif , direntry , & count , 8 , & origdata , maxcount ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG8 :
* value = ( uint64 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong8 ( * value , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
case TIFF_SLONG8 :
{
int64 * m ;
uint32 n ;
m = ( int64 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) m ) ;
err = TIFFReadDirEntryCheckRangeLong8Slong8 ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( uint64 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
}
data = ( uint64 * ) _TIFFmalloc ( count * 8 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( uint64 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
err = TIFFReadDirEntryCheckRangeLong8Sbyte ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeLong8Sshort ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
err = TIFFReadDirEntryCheckRangeLong8Slong ( * ma ) ;
if ( err ! = TIFFReadDirEntryErrOk )
break ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( data ) ;
return ( err ) ;
}
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryLong8Array ( TIFF * tif , TIFFDirEntry * direntry , uint64 * * value )
{
return TIFFReadDirEntryLong8ArrayWithLimit ( tif , direntry , value , ~ ( ( uint64 ) 0 ) ) ;
}
static enum TIFFReadDirEntryErr TIFFReadDirEntrySlong8Array ( TIFF * tif , TIFFDirEntry * direntry , int64 * * value )
{
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
int64 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 8 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG8 :
{
uint64 * m ;
uint32 n ;
m = ( uint64 * ) origdata ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( m ) ;
err = TIFFReadDirEntryCheckRangeSlong8Long8 ( * m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
_TIFFfree ( origdata ) ;
return ( err ) ;
}
m + + ;
}
* value = ( int64 * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
case TIFF_SLONG8 :
* value = ( int64 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong8 ( ( uint64 * ) ( * value ) , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( int64 * ) _TIFFmalloc ( count * 8 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
int64 * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int64 ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
int64 * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( int64 ) ( * ma + + ) ;
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
int64 * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( int64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
int64 * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
* mb + + = ( int64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
int64 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
* mb + + = ( int64 ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
int64 * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
* mb + + = ( int64 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryFloatArray ( TIFF * tif , TIFFDirEntry * direntry , float * * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
float * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
case TIFF_RATIONAL :
case TIFF_SRATIONAL :
case TIFF_FLOAT :
case TIFF_DOUBLE :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 4 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_FLOAT :
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( ( uint32 * ) origdata , count ) ;
TIFFCvtIEEEDoubleToNative ( tif , count , ( float * ) origdata ) ;
* value = ( float * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( float * ) _TIFFmalloc ( count * sizeof ( float ) ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
float * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( float ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
float * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( float ) ( * ma + + ) ;
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
float * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( float ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
float * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
* mb + + = ( float ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
float * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
* mb + + = ( float ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
float * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
* mb + + = ( float ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
float * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
2012-02-29 23:01:28 +08:00
# if defined(__WIN32__) && (_MSC_VER < 1500)
2017-12-08 20:47:54 +08:00
/*
* XXX : MSVC 6.0 does not support
* conversion of 64 - bit integers into
* floating point values .
*/
* mb + + = _TIFFUInt64ToFloat ( * ma + + ) ;
2012-02-29 23:01:28 +08:00
# else
2017-12-08 20:47:54 +08:00
* mb + + = ( float ) ( * ma + + ) ;
2012-02-29 23:01:28 +08:00
# endif
2017-12-08 20:47:54 +08:00
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
float * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
* mb + + = ( float ) ( * ma + + ) ;
}
}
break ;
case TIFF_RATIONAL :
{
uint32 * ma ;
uint32 maa ;
uint32 mab ;
float * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
maa = * ma + + ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
mab = * ma + + ;
if ( mab = = 0 )
* mb + + = 0.0 ;
else
* mb + + = ( float ) maa / ( float ) mab ;
}
}
break ;
case TIFF_SRATIONAL :
{
uint32 * ma ;
int32 maa ;
uint32 mab ;
float * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
maa = * ( int32 * ) ma ;
ma + + ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
mab = * ma + + ;
if ( mab = = 0 )
* mb + + = 0.0 ;
else
* mb + + = ( float ) maa / ( float ) mab ;
}
}
break ;
case TIFF_DOUBLE :
{
double * ma ;
float * mb ;
uint32 n ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong8 ( ( uint64 * ) origdata , count ) ;
TIFFCvtIEEEDoubleToNative ( tif , count , ( double * ) origdata ) ;
ma = ( double * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
double val = * ma + + ;
if ( val > FLT_MAX )
val = FLT_MAX ;
else if ( val < - FLT_MAX )
val = - FLT_MAX ;
* mb + + = ( float ) val ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryDoubleArray ( TIFF * tif , TIFFDirEntry * direntry , double * * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
double * data ;
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
case TIFF_SBYTE :
case TIFF_SHORT :
case TIFF_SSHORT :
case TIFF_LONG :
case TIFF_SLONG :
case TIFF_LONG8 :
case TIFF_SLONG8 :
case TIFF_RATIONAL :
case TIFF_SRATIONAL :
case TIFF_FLOAT :
case TIFF_DOUBLE :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 8 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_DOUBLE :
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong8 ( ( uint64 * ) origdata , count ) ;
TIFFCvtIEEEDoubleToNative ( tif , count , ( double * ) origdata ) ;
* value = ( double * ) origdata ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( double * ) _TIFFmalloc ( count * sizeof ( double ) ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_BYTE :
{
uint8 * ma ;
double * mb ;
uint32 n ;
ma = ( uint8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( double ) ( * ma + + ) ;
}
break ;
case TIFF_SBYTE :
{
int8 * ma ;
double * mb ;
uint32 n ;
ma = ( int8 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( double ) ( * ma + + ) ;
}
break ;
case TIFF_SHORT :
{
uint16 * ma ;
double * mb ;
uint32 n ;
ma = ( uint16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ma ) ;
* mb + + = ( double ) ( * ma + + ) ;
}
}
break ;
case TIFF_SSHORT :
{
int16 * ma ;
double * mb ;
uint32 n ;
ma = ( int16 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
* mb + + = ( double ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG :
{
uint32 * ma ;
double * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
* mb + + = ( double ) ( * ma + + ) ;
}
}
break ;
case TIFF_SLONG :
{
int32 * ma ;
double * mb ;
uint32 n ;
ma = ( int32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
* mb + + = ( double ) ( * ma + + ) ;
}
}
break ;
case TIFF_LONG8 :
{
uint64 * ma ;
double * mb ;
uint32 n ;
ma = ( uint64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ma ) ;
2012-02-29 23:01:28 +08:00
# if defined(__WIN32__) && (_MSC_VER < 1500)
2017-12-08 20:47:54 +08:00
/*
* XXX : MSVC 6.0 does not support
* conversion of 64 - bit integers into
* floating point values .
*/
* mb + + = _TIFFUInt64ToDouble ( * ma + + ) ;
2012-02-29 23:01:28 +08:00
# else
2017-12-08 20:47:54 +08:00
* mb + + = ( double ) ( * ma + + ) ;
2012-02-29 23:01:28 +08:00
# endif
2017-12-08 20:47:54 +08:00
}
}
break ;
case TIFF_SLONG8 :
{
int64 * ma ;
double * mb ;
uint32 n ;
ma = ( int64 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
* mb + + = ( double ) ( * ma + + ) ;
}
}
break ;
case TIFF_RATIONAL :
{
uint32 * ma ;
uint32 maa ;
uint32 mab ;
double * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
maa = * ma + + ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
mab = * ma + + ;
if ( mab = = 0 )
* mb + + = 0.0 ;
else
* mb + + = ( double ) maa / ( double ) mab ;
}
}
break ;
case TIFF_SRATIONAL :
{
uint32 * ma ;
int32 maa ;
uint32 mab ;
double * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
maa = * ( int32 * ) ma ;
ma + + ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
mab = * ma + + ;
if ( mab = = 0 )
* mb + + = 0.0 ;
else
* mb + + = ( double ) maa / ( double ) mab ;
}
}
break ;
case TIFF_FLOAT :
{
float * ma ;
double * mb ;
uint32 n ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( ( uint32 * ) origdata , count ) ;
TIFFCvtIEEEFloatToNative ( tif , count , ( float * ) origdata ) ;
ma = ( float * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
* mb + + = ( double ) ( * ma + + ) ;
}
break ;
}
_TIFFfree ( origdata ) ;
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8Array ( TIFF * tif , TIFFDirEntry * direntry , uint64 * * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint32 count ;
void * origdata ;
uint64 * data ;
switch ( direntry - > tdir_type )
{
case TIFF_LONG :
case TIFF_LONG8 :
case TIFF_IFD :
case TIFF_IFD8 :
break ;
default :
return ( TIFFReadDirEntryErrType ) ;
}
err = TIFFReadDirEntryArray ( tif , direntry , & count , 8 , & origdata ) ;
if ( ( err ! = TIFFReadDirEntryErrOk ) | | ( origdata = = 0 ) )
{
* value = 0 ;
return ( err ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG8 :
case TIFF_IFD8 :
* value = ( uint64 * ) origdata ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong8 ( * value , count ) ;
return ( TIFFReadDirEntryErrOk ) ;
}
data = ( uint64 * ) _TIFFmalloc ( count * 8 ) ;
if ( data = = 0 )
{
_TIFFfree ( origdata ) ;
return ( TIFFReadDirEntryErrAlloc ) ;
}
switch ( direntry - > tdir_type )
{
case TIFF_LONG :
case TIFF_IFD :
{
uint32 * ma ;
uint64 * mb ;
uint32 n ;
ma = ( uint32 * ) origdata ;
mb = data ;
for ( n = 0 ; n < count ; n + + )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ma ) ;
* mb + + = ( uint64 ) ( * ma + + ) ;
}
}
break ;
}
_TIFFfree ( origdata ) ;
* value = data ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
uint16 * m ;
uint16 * na ;
uint16 nb ;
if ( direntry - > tdir_count < ( uint64 ) tif - > tif_dir . td_samplesperpixel )
return ( TIFFReadDirEntryErrCount ) ;
err = TIFFReadDirEntryShortArray ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk | | m = = NULL )
return ( err ) ;
na = m ;
nb = tif - > tif_dir . td_samplesperpixel ;
* value = * na + + ;
nb - - ;
while ( nb > 0 )
{
if ( * na + + ! = * value )
{
err = TIFFReadDirEntryErrPsdif ;
break ;
}
nb - - ;
}
_TIFFfree ( m ) ;
return ( err ) ;
2012-02-29 23:01:28 +08:00
}
#if 0
static enum TIFFReadDirEntryErr TIFFReadDirEntryPersampleDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value )
{
2017-12-08 20:47:54 +08:00
enum TIFFReadDirEntryErr err ;
double * m ;
double * na ;
uint16 nb ;
if ( direntry - > tdir_count < ( uint64 ) tif - > tif_dir . td_samplesperpixel )
return ( TIFFReadDirEntryErrCount ) ;
err = TIFFReadDirEntryDoubleArray ( tif , direntry , & m ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
na = m ;
nb = tif - > tif_dir . td_samplesperpixel ;
* value = * na + + ;
nb - - ;
while ( nb > 0 )
{
if ( * na + + ! = * value )
{
err = TIFFReadDirEntryErrPsdif ;
break ;
}
nb - - ;
}
_TIFFfree ( m ) ;
return ( err ) ;
2012-02-29 23:01:28 +08:00
}
# endif
static void TIFFReadDirEntryCheckedByte ( TIFF * tif , TIFFDirEntry * direntry , uint8 * value )
{
2017-12-08 20:47:54 +08:00
( void ) tif ;
* value = * ( uint8 * ) ( & direntry - > tdir_offset ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedSbyte ( TIFF * tif , TIFFDirEntry * direntry , int8 * value )
{
2017-12-08 20:47:54 +08:00
( void ) tif ;
* value = * ( int8 * ) ( & direntry - > tdir_offset ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedShort ( TIFF * tif , TIFFDirEntry * direntry , uint16 * value )
{
2017-12-08 20:47:54 +08:00
* value = direntry - > tdir_offset . toff_short ;
/* *value=*(uint16*)(&direntry->tdir_offset); */
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( value ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedSshort ( TIFF * tif , TIFFDirEntry * direntry , int16 * value )
{
2017-12-08 20:47:54 +08:00
* value = * ( int16 * ) ( & direntry - > tdir_offset ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) value ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedLong ( TIFF * tif , TIFFDirEntry * direntry , uint32 * value )
{
2017-12-08 20:47:54 +08:00
* value = * ( uint32 * ) ( & direntry - > tdir_offset ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( value ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedSlong ( TIFF * tif , TIFFDirEntry * direntry , int32 * value )
{
2017-12-08 20:47:54 +08:00
* value = * ( int32 * ) ( & direntry - > tdir_offset ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) value ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedLong8 ( TIFF * tif , TIFFDirEntry * direntry , uint64 * value )
{
2017-12-08 20:47:54 +08:00
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
}
else
* value = direntry - > tdir_offset . toff_long8 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( value ) ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSlong8 ( TIFF * tif , TIFFDirEntry * direntry , int64 * value )
{
2017-12-08 20:47:54 +08:00
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
}
else
* value = * ( int64 * ) ( & direntry - > tdir_offset ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) value ) ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedRational ( TIFF * tif , TIFFDirEntry * direntry , double * value )
{
2017-12-08 20:47:54 +08:00
UInt64Aligned_t m ;
assert ( sizeof ( double ) = = 8 ) ;
assert ( sizeof ( uint64 ) = = 8 ) ;
assert ( sizeof ( uint32 ) = = 4 ) ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , m . i ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
}
else
m . l = direntry - > tdir_offset . toff_long8 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( m . i , 2 ) ;
/* Not completely sure what we should do when m.i[1]==0, but some */
/* sanitizers do not like division by 0.0: */
/* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
if ( m . i [ 0 ] = = 0 | | m . i [ 1 ] = = 0 )
* value = 0.0 ;
else
* value = ( double ) m . i [ 0 ] / ( double ) m . i [ 1 ] ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedSrational ( TIFF * tif , TIFFDirEntry * direntry , double * value )
{
2017-12-08 20:47:54 +08:00
UInt64Aligned_t m ;
assert ( sizeof ( double ) = = 8 ) ;
assert ( sizeof ( uint64 ) = = 8 ) ;
assert ( sizeof ( int32 ) = = 4 ) ;
assert ( sizeof ( uint32 ) = = 4 ) ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , m . i ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
}
else
m . l = direntry - > tdir_offset . toff_long8 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( m . i , 2 ) ;
/* Not completely sure what we should do when m.i[1]==0, but some */
/* sanitizers do not like division by 0.0: */
/* http://bugzilla.maptools.org/show_bug.cgi?id=2644 */
if ( ( int32 ) m . i [ 0 ] = = 0 | | m . i [ 1 ] = = 0 )
* value = 0.0 ;
else
* value = ( double ) ( ( int32 ) m . i [ 0 ] ) / ( double ) m . i [ 1 ] ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryCheckedFloat ( TIFF * tif , TIFFDirEntry * direntry , float * value )
{
union
2017-12-08 20:47:54 +08:00
{
float f ;
uint32 i ;
} float_union ;
assert ( sizeof ( float ) = = 4 ) ;
assert ( sizeof ( uint32 ) = = 4 ) ;
assert ( sizeof ( float_union ) = = 4 ) ;
float_union . i = * ( uint32 * ) ( & direntry - > tdir_offset ) ;
* value = float_union . f ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) value ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckedDouble ( TIFF * tif , TIFFDirEntry * direntry , double * value )
{
2017-12-08 20:47:54 +08:00
assert ( sizeof ( double ) = = 8 ) ;
assert ( sizeof ( uint64 ) = = 8 ) ;
assert ( sizeof ( UInt64Aligned_t ) = = 8 ) ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
enum TIFFReadDirEntryErr err ;
uint32 offset = direntry - > tdir_offset . toff_long ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
return ( err ) ;
}
else
{
UInt64Aligned_t uint64_union ;
uint64_union . l = direntry - > tdir_offset . toff_long8 ;
* value = uint64_union . d ;
}
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) value ) ;
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSbyte ( int8 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteShort ( uint16 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0xFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSshort ( int16 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > 0xFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong ( uint32 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0xFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > 0xFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0xFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeByteSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > 0xFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteByte ( uint8 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7F )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteShort ( uint16 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7F )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSshort ( int16 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < - 0x80 ) | | ( value > 0x7F ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong ( uint32 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7F )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < - 0x80 ) | | ( value > 0x7F ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7F )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSbyteSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < - 0x80 ) | | ( value > 0x7F ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSbyte ( int8 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSshort ( int16 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong ( uint32 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0xFFFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > 0xFFFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0xFFFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeShortSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > 0xFFFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortShort ( uint16 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7FFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong ( uint32 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7FFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < - 0x8000 ) | | ( value > 0x7FFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7FFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeSshortSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < - 0x8000 ) | | ( value > 0x7FFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSbyte ( int8 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSshort ( int16 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > TIFF_UINT32_MAX )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 ) | | ( value > ( int64 ) TIFF_UINT32_MAX ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongLong ( uint32 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7FFFFFFFUL )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
/* Check that the 8-byte unsigned value can fit in a 4-byte unsigned range */
2012-02-29 23:01:28 +08:00
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongLong8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > 0x7FFFFFFF )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
2017-12-08 20:47:54 +08:00
/* Check that the 8-byte signed value can fit in a 4-byte signed range */
2012-02-29 23:01:28 +08:00
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongSlong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( ( value < 0 - ( ( int64 ) 0x7FFFFFFF + 1 ) ) | | ( value > 0x7FFFFFFF ) )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Sbyte ( int8 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Sshort ( int16 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Slong ( int32 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Slong8 ( int64 value )
{
2017-12-08 20:47:54 +08:00
if ( value < 0 )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlong8Long8 ( uint64 value )
{
2017-12-08 20:47:54 +08:00
if ( value > TIFF_INT64_MAX )
return ( TIFFReadDirEntryErrRange ) ;
else
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryData ( TIFF * tif , uint64 offset , tmsize_t size , void * dest )
{
2017-12-08 20:47:54 +08:00
assert ( size > 0 ) ;
if ( ! isMapped ( tif ) ) {
if ( ! SeekOK ( tif , offset ) )
return ( TIFFReadDirEntryErrIo ) ;
if ( ! ReadOK ( tif , dest , size ) )
return ( TIFFReadDirEntryErrIo ) ;
} else {
size_t ma , mb ;
ma = ( size_t ) offset ;
2021-03-02 07:17:30 +08:00
if ( ( uint64 ) ma ! = offset | |
ma > ( ~ ( size_t ) 0 ) - ( size_t ) size )
{
return TIFFReadDirEntryErrIo ;
}
2017-12-08 20:47:54 +08:00
mb = ma + size ;
2021-03-02 07:17:30 +08:00
if ( mb > ( uint64 ) tif - > tif_size )
2017-12-08 20:47:54 +08:00
return ( TIFFReadDirEntryErrIo ) ;
_TIFFmemcpy ( dest , tif - > tif_base + ma , size ) ;
}
return ( TIFFReadDirEntryErrOk ) ;
2012-02-29 23:01:28 +08:00
}
static void TIFFReadDirEntryOutputErr ( TIFF * tif , enum TIFFReadDirEntryErr err , const char * module , const char * tagname , int recover )
{
2017-12-08 20:47:54 +08:00
if ( ! recover ) {
switch ( err ) {
case TIFFReadDirEntryErrCount :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Incorrect count for \" %s \" " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrType :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Incompatible type for \" %s \" " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrIo :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" IO error during reading of \" %s \" " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrRange :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Incorrect value for \" %s \" " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrPsdif :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot handle different values per sample for \" %s \" " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrSizesan :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on size of \" %s \" value failed " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrAlloc :
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Out of memory reading of \" %s \" " ,
tagname ) ;
break ;
default :
assert ( 0 ) ; /* we should never get here */
break ;
}
} else {
switch ( err ) {
case TIFFReadDirEntryErrCount :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Incorrect count for \" %s \" ; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrType :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Incompatible type for \" %s \" ; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrIo :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" IO error during reading of \" %s \" ; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrRange :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Incorrect value for \" %s \" ; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrPsdif :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Cannot handle different values per sample for \" %s \" ; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrSizesan :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Sanity check on size of \" %s \" value failed; tag ignored " ,
tagname ) ;
break ;
case TIFFReadDirEntryErrAlloc :
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Out of memory reading of \" %s \" ; tag ignored " ,
tagname ) ;
break ;
default :
assert ( 0 ) ; /* we should never get here */
break ;
}
}
2012-02-29 23:01:28 +08:00
}
2010-05-12 01:44:00 +08:00
2019-02-12 21:43:58 +08:00
/*
* Return the maximum number of color channels specified for a given photometric
* type . 0 is returned if photometric type isn ' t supported or no default value
* is defined by the specification .
*/
static int _TIFFGetMaxColorChannels ( uint16 photometric )
{
switch ( photometric ) {
case PHOTOMETRIC_PALETTE :
case PHOTOMETRIC_MINISWHITE :
case PHOTOMETRIC_MINISBLACK :
return 1 ;
case PHOTOMETRIC_YCBCR :
case PHOTOMETRIC_RGB :
case PHOTOMETRIC_CIELAB :
case PHOTOMETRIC_LOGLUV :
case PHOTOMETRIC_ITULAB :
case PHOTOMETRIC_ICCLAB :
return 3 ;
case PHOTOMETRIC_SEPARATED :
case PHOTOMETRIC_MASK :
return 4 ;
case PHOTOMETRIC_LOGL :
case PHOTOMETRIC_CFA :
default :
return 0 ;
}
}
2021-03-02 07:17:30 +08:00
static int ByteCountLooksBad ( TIFF * tif )
{
/*
* Assume we have wrong StripByteCount value ( in case
* of single strip ) in following cases :
* - it is equal to zero along with StripOffset ;
* - it is larger than file itself ( in case of uncompressed
* image ) ;
* - it is smaller than the size of the bytes per row
* multiplied on the number of rows . The last case should
* not be checked in the case of writing new image ,
* because we may do not know the exact strip size
* until the whole image will be written and directory
* dumped out .
*/
uint64 bytecount = TIFFGetStrileByteCount ( tif , 0 ) ;
uint64 offset = TIFFGetStrileOffset ( tif , 0 ) ;
uint64 filesize ;
if ( offset = = 0 )
return 0 ;
if ( bytecount = = 0 )
return 1 ;
if ( tif - > tif_dir . td_compression ! = COMPRESSION_NONE )
return 0 ;
filesize = TIFFGetFileSize ( tif ) ;
if ( offset < = filesize & & bytecount > filesize - offset )
return 1 ;
if ( tif - > tif_mode = = O_RDONLY )
{
uint64 scanlinesize = TIFFScanlineSize64 ( tif ) ;
if ( tif - > tif_dir . td_imagelength > 0 & &
scanlinesize > TIFF_UINT64_MAX / tif - > tif_dir . td_imagelength )
{
return 1 ;
}
if ( bytecount < scanlinesize * tif - > tif_dir . td_imagelength )
return 1 ;
}
return 0 ;
}
2010-05-12 01:44:00 +08:00
/*
2010-07-16 20:54:53 +08:00
* Read the next TIFF directory from a file and convert it to the internal
* format . We read directories sequentially .
2010-05-12 01:44:00 +08:00
*/
int
TIFFReadDirectory ( TIFF * tif )
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFReadDirectory " ;
TIFFDirEntry * dir ;
uint16 dircount ;
TIFFDirEntry * dp ;
uint16 di ;
const TIFFField * fip ;
uint32 fii = FAILED_FII ;
2012-02-29 23:01:28 +08:00
toff_t nextdiroff ;
2017-12-08 20:47:54 +08:00
int bitspersample_read = FALSE ;
2019-02-12 21:43:58 +08:00
int color_channels ;
2017-12-08 20:47:54 +08:00
tif - > tif_diroff = tif - > tif_nextdiroff ;
if ( ! TIFFCheckDirOffset ( tif , tif - > tif_nextdiroff ) )
return 0 ; /* last offset or bad offset (IFD looping) */
( * tif - > tif_cleanup ) ( tif ) ; /* cleanup any previous compression state */
tif - > tif_curdir + + ;
2012-02-29 23:01:28 +08:00
nextdiroff = tif - > tif_nextdiroff ;
2017-12-08 20:47:54 +08:00
dircount = TIFFFetchDirectory ( tif , nextdiroff , & dir , & tif - > tif_nextdiroff ) ;
if ( ! dircount )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Failed to read directory at offset " TIFF_UINT64_FORMAT , nextdiroff ) ;
return 0 ;
}
TIFFReadDirectoryCheckOrder ( tif , dir , dircount ) ;
2012-02-29 23:01:28 +08:00
/*
* Mark duplicates of any tag to be ignored ( bugzilla 1994 )
* to avoid certain pathological problems .
*/
2017-12-08 20:47:54 +08:00
{
TIFFDirEntry * ma ;
uint16 mb ;
for ( ma = dir , mb = 0 ; mb < dircount ; ma + + , mb + + )
{
TIFFDirEntry * na ;
uint16 nb ;
for ( na = ma + 1 , nb = mb + 1 ; nb < dircount ; na + + , nb + + )
{
2021-03-02 07:17:30 +08:00
if ( ma - > tdir_tag = = na - > tdir_tag ) {
na - > tdir_ignore = TRUE ;
}
2017-12-08 20:47:54 +08:00
}
}
}
tif - > tif_flags & = ~ TIFF_BEENWRITING ; /* reset before new dir */
tif - > tif_flags & = ~ TIFF_BUF4WRITE ; /* reset before new dir */
2021-03-02 07:17:30 +08:00
tif - > tif_flags & = ~ TIFF_CHOPPEDUPARRAYS ;
2017-12-08 20:47:54 +08:00
/* free any old stuff and reinit */
TIFFFreeDirectory ( tif ) ;
TIFFDefaultDirectory ( tif ) ;
/*
* Electronic Arts writes gray - scale TIFF files
* without a PlanarConfiguration directory entry .
* Thus we setup a default value here , even though
* the TIFF spec says there is no default value .
*/
TIFFSetField ( tif , TIFFTAG_PLANARCONFIG , PLANARCONFIG_CONTIG ) ;
/*
* Setup default value and then make a pass over
* the fields to check type and tag information ,
* and to extract info required to size data
* structures . A second pass is made afterwards
* to read in everything not taken in the first pass .
* But we must process the Compression tag first
* in order to merge in codec - private tag definitions ( otherwise
* we may get complaints about unknown tags ) . However , the
* Compression tag may be dependent on the SamplesPerPixel
* tag value because older TIFF specs permitted Compression
* to be written as a SamplesPerPixel - count tag entry .
* Thus if we don ' t first figure out the correct SamplesPerPixel
* tag value then we may end up ignoring the Compression tag
* value because it has an incorrect count value ( if the
* true value of SamplesPerPixel is not 1 ) .
*/
dp = TIFFReadDirectoryFindEntry ( tif , dir , dircount , TIFFTAG_SAMPLESPERPIXEL ) ;
if ( dp )
{
if ( ! TIFFFetchNormalTag ( tif , dp , 0 ) )
goto bad ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
}
dp = TIFFReadDirectoryFindEntry ( tif , dir , dircount , TIFFTAG_COMPRESSION ) ;
if ( dp )
{
/*
* The 5.0 spec says the Compression tag has one value , while
* earlier specs say it has one value per sample . Because of
* this , we accept the tag if one value is supplied with either
* count .
*/
uint16 value ;
enum TIFFReadDirEntryErr err ;
err = TIFFReadDirEntryShort ( tif , dp , & value ) ;
if ( err = = TIFFReadDirEntryErrCount )
err = TIFFReadDirEntryPersampleShort ( tif , dp , & value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
TIFFReadDirEntryOutputErr ( tif , err , module , " Compression " , 0 ) ;
goto bad ;
}
if ( ! TIFFSetField ( tif , TIFFTAG_COMPRESSION , value ) )
goto bad ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
}
else
{
if ( ! TIFFSetField ( tif , TIFFTAG_COMPRESSION , COMPRESSION_NONE ) )
goto bad ;
}
/*
* First real pass over the directory .
*/
for ( di = 0 , dp = dir ; di < dircount ; di + + , dp + + )
{
2021-03-02 07:17:30 +08:00
if ( ! dp - > tdir_ignore )
2017-12-08 20:47:54 +08:00
{
TIFFReadDirectoryFindFieldInfo ( tif , dp - > tdir_tag , & fii ) ;
if ( fii = = FAILED_FII )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Unknown field with tag %d (0x%x) encountered " ,
dp - > tdir_tag , dp - > tdir_tag ) ;
2021-03-02 07:17:30 +08:00
/* the following knowingly leaks the
anonymous field structure */
2017-12-08 20:47:54 +08:00
if ( ! _TIFFMergeFields ( tif ,
_TIFFCreateAnonField ( tif ,
dp - > tdir_tag ,
( TIFFDataType ) dp - > tdir_type ) ,
1 ) ) {
TIFFWarningExt ( tif - > tif_clientdata ,
module ,
" Registering anonymous field with tag %d (0x%x) failed " ,
dp - > tdir_tag ,
dp - > tdir_tag ) ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
} else {
TIFFReadDirectoryFindFieldInfo ( tif , dp - > tdir_tag , & fii ) ;
assert ( fii ! = FAILED_FII ) ;
}
}
}
2021-03-02 07:17:30 +08:00
if ( ! dp - > tdir_ignore )
2017-12-08 20:47:54 +08:00
{
fip = tif - > tif_fields [ fii ] ;
if ( fip - > field_bit = = FIELD_IGNORE )
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
else
{
switch ( dp - > tdir_tag )
{
case TIFFTAG_STRIPOFFSETS :
case TIFFTAG_STRIPBYTECOUNTS :
case TIFFTAG_TILEOFFSETS :
case TIFFTAG_TILEBYTECOUNTS :
TIFFSetFieldBit ( tif , fip - > field_bit ) ;
break ;
case TIFFTAG_IMAGEWIDTH :
case TIFFTAG_IMAGELENGTH :
case TIFFTAG_IMAGEDEPTH :
case TIFFTAG_TILELENGTH :
case TIFFTAG_TILEWIDTH :
case TIFFTAG_TILEDEPTH :
case TIFFTAG_PLANARCONFIG :
case TIFFTAG_ROWSPERSTRIP :
case TIFFTAG_EXTRASAMPLES :
if ( ! TIFFFetchNormalTag ( tif , dp , 0 ) )
goto bad ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
break ;
default :
if ( ! _TIFFCheckFieldIsValidForCodec ( tif , dp - > tdir_tag ) )
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
break ;
}
}
}
}
/*
* XXX : OJPEG hack .
* If a ) compression is OJPEG , b ) planarconfig tag says it ' s separate ,
* c ) strip offsets / bytecounts tag are both present and
* d ) both contain exactly one value , then we consistently find
* that the buggy implementation of the buggy compression scheme
* matches contig planarconfig best . So we ' fix - up ' the tag here
*/
if ( ( tif - > tif_dir . td_compression = = COMPRESSION_OJPEG ) & &
( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_SEPARATE ) )
{
2021-03-02 07:17:30 +08:00
if ( ! _TIFFFillStriles ( tif ) )
goto bad ;
2017-12-08 20:47:54 +08:00
dp = TIFFReadDirectoryFindEntry ( tif , dir , dircount , TIFFTAG_STRIPOFFSETS ) ;
if ( ( dp ! = 0 ) & & ( dp - > tdir_count = = 1 ) )
{
dp = TIFFReadDirectoryFindEntry ( tif , dir , dircount ,
TIFFTAG_STRIPBYTECOUNTS ) ;
if ( ( dp ! = 0 ) & & ( dp - > tdir_count = = 1 ) )
{
tif - > tif_dir . td_planarconfig = PLANARCONFIG_CONTIG ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Planarconfig tag value assumed incorrect, "
" assuming data is contig instead of chunky " ) ;
}
}
}
/*
* Allocate directory structure and setup defaults .
*/
if ( ! TIFFFieldSet ( tif , FIELD_IMAGEDIMENSIONS ) )
{
MissingRequired ( tif , " ImageLength " ) ;
goto bad ;
}
/*
* Setup appropriate structures ( by strip or by tile )
*/
if ( ! TIFFFieldSet ( tif , FIELD_TILEDIMENSIONS ) ) {
tif - > tif_dir . td_nstrips = TIFFNumberOfStrips ( tif ) ;
tif - > tif_dir . td_tilewidth = tif - > tif_dir . td_imagewidth ;
tif - > tif_dir . td_tilelength = tif - > tif_dir . td_rowsperstrip ;
tif - > tif_dir . td_tiledepth = tif - > tif_dir . td_imagedepth ;
tif - > tif_flags & = ~ TIFF_ISTILED ;
} else {
tif - > tif_dir . td_nstrips = TIFFNumberOfTiles ( tif ) ;
tif - > tif_flags | = TIFF_ISTILED ;
}
if ( ! tif - > tif_dir . td_nstrips ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot handle zero number of %s " ,
isTiled ( tif ) ? " tiles " : " strips " ) ;
goto bad ;
}
tif - > tif_dir . td_stripsperimage = tif - > tif_dir . td_nstrips ;
if ( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_SEPARATE )
tif - > tif_dir . td_stripsperimage / = tif - > tif_dir . td_samplesperpixel ;
if ( ! TIFFFieldSet ( tif , FIELD_STRIPOFFSETS ) ) {
# ifdef OJPEG_SUPPORT
if ( ( tif - > tif_dir . td_compression = = COMPRESSION_OJPEG ) & &
( isTiled ( tif ) = = 0 ) & &
( tif - > tif_dir . td_nstrips = = 1 ) ) {
/*
* XXX : OJPEG hack .
* If a ) compression is OJPEG , b ) it ' s not a tiled TIFF ,
* and c ) the number of strips is 1 ,
* then we tolerate the absence of stripoffsets tag ,
* because , presumably , all required data is in the
* JpegInterchangeFormat stream .
*/
TIFFSetFieldBit ( tif , FIELD_STRIPOFFSETS ) ;
} else
# endif
2012-10-17 15:12:04 +08:00
{
2017-12-08 20:47:54 +08:00
MissingRequired ( tif ,
isTiled ( tif ) ? " TileOffsets " : " StripOffsets " ) ;
goto bad ;
}
}
/*
* Second pass : extract other information .
*/
for ( di = 0 , dp = dir ; di < dircount ; di + + , dp + + )
{
2021-03-02 07:17:30 +08:00
if ( ! dp - > tdir_ignore ) {
switch ( dp - > tdir_tag )
{
case TIFFTAG_MINSAMPLEVALUE :
case TIFFTAG_MAXSAMPLEVALUE :
case TIFFTAG_BITSPERSAMPLE :
case TIFFTAG_DATATYPE :
case TIFFTAG_SAMPLEFORMAT :
/*
* The MinSampleValue , MaxSampleValue , BitsPerSample
* DataType and SampleFormat tags are supposed to be
* written as one value / sample , but some vendors
* incorrectly write one value only - - so we accept
* that as well ( yuck ) . Other vendors write correct
* value for NumberOfSamples , but incorrect one for
* BitsPerSample and friends , and we will read this
* too .
*/
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
uint16 value ;
enum TIFFReadDirEntryErr err ;
err = TIFFReadDirEntryShort ( tif , dp , & value ) ;
if ( err = = TIFFReadDirEntryErrCount )
err = TIFFReadDirEntryPersampleShort ( tif , dp , & value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFReadDirEntryOutputErr ( tif , err , module , fip ? fip - > field_name : " unknown tagname " , 0 ) ;
goto bad ;
}
if ( ! TIFFSetField ( tif , dp - > tdir_tag , value ) )
goto bad ;
if ( dp - > tdir_tag = = TIFFTAG_BITSPERSAMPLE )
bitspersample_read = TRUE ;
2017-12-08 20:47:54 +08:00
}
2021-03-02 07:17:30 +08:00
break ;
case TIFFTAG_SMINSAMPLEVALUE :
case TIFFTAG_SMAXSAMPLEVALUE :
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
double * data = NULL ;
enum TIFFReadDirEntryErr err ;
uint32 saved_flags ;
int m ;
if ( dp - > tdir_count ! = ( uint64 ) tif - > tif_dir . td_samplesperpixel )
err = TIFFReadDirEntryErrCount ;
else
err = TIFFReadDirEntryDoubleArray ( tif , dp , & data ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFReadDirEntryOutputErr ( tif , err , module , fip ? fip - > field_name : " unknown tagname " , 0 ) ;
goto bad ;
}
saved_flags = tif - > tif_flags ;
tif - > tif_flags | = TIFF_PERSAMPLE ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
tif - > tif_flags = saved_flags ;
_TIFFfree ( data ) ;
if ( ! m )
goto bad ;
2017-12-08 20:47:54 +08:00
}
2021-03-02 07:17:30 +08:00
break ;
case TIFFTAG_STRIPOFFSETS :
case TIFFTAG_TILEOFFSETS :
switch ( dp - > tdir_type )
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
case TIFF_SHORT :
case TIFF_LONG :
case TIFF_LONG8 :
break ;
default :
/* Warn except if directory typically created with TIFFDeferStrileArrayWriting() */
if ( ! ( tif - > tif_mode = = O_RDWR & &
dp - > tdir_count = = 0 & &
dp - > tdir_type = = 0 & &
dp - > tdir_offset . toff_long8 = = 0 ) )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Invalid data type for tag %s " ,
fip ? fip - > field_name : " unknown tagname " ) ;
}
break ;
}
_TIFFmemcpy ( & ( tif - > tif_dir . td_stripoffset_entry ) ,
dp , sizeof ( TIFFDirEntry ) ) ;
break ;
case TIFFTAG_STRIPBYTECOUNTS :
case TIFFTAG_TILEBYTECOUNTS :
switch ( dp - > tdir_type )
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
case TIFF_SHORT :
case TIFF_LONG :
case TIFF_LONG8 :
break ;
default :
/* Warn except if directory typically created with TIFFDeferStrileArrayWriting() */
if ( ! ( tif - > tif_mode = = O_RDWR & &
dp - > tdir_count = = 0 & &
dp - > tdir_type = = 0 & &
dp - > tdir_offset . toff_long8 = = 0 ) )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Invalid data type for tag %s " ,
fip ? fip - > field_name : " unknown tagname " ) ;
}
break ;
}
_TIFFmemcpy ( & ( tif - > tif_dir . td_stripbytecount_entry ) ,
dp , sizeof ( TIFFDirEntry ) ) ;
break ;
case TIFFTAG_COLORMAP :
case TIFFTAG_TRANSFERFUNCTION :
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
enum TIFFReadDirEntryErr err ;
uint32 countpersample ;
uint32 countrequired ;
uint32 incrementpersample ;
uint16 * value = NULL ;
/* It would be dangerous to instantiate those tag values */
/* since if td_bitspersample has not yet been read (due to */
/* unordered tags), it could be read afterwards with a */
/* values greater than the default one (1), which may cause */
/* crashes in user code */
if ( ! bitspersample_read )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Ignoring %s since BitsPerSample tag not found " ,
fip ? fip - > field_name : " unknown tagname " ) ;
continue ;
}
/* ColorMap or TransferFunction for high bit */
/* depths do not make much sense and could be */
/* used as a denial of service vector */
if ( tif - > tif_dir . td_bitspersample > 24 )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Ignoring %s because BitsPerSample=%d>24 " ,
fip ? fip - > field_name : " unknown tagname " ,
tif - > tif_dir . td_bitspersample ) ;
continue ;
}
countpersample = ( 1U < < tif - > tif_dir . td_bitspersample ) ;
if ( ( dp - > tdir_tag = = TIFFTAG_TRANSFERFUNCTION ) & & ( dp - > tdir_count = = ( uint64 ) countpersample ) )
{
countrequired = countpersample ;
incrementpersample = 0 ;
}
else
{
countrequired = 3 * countpersample ;
incrementpersample = countpersample ;
}
if ( dp - > tdir_count ! = ( uint64 ) countrequired )
err = TIFFReadDirEntryErrCount ;
else
err = TIFFReadDirEntryShortArray ( tif , dp , & value ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
fip = TIFFFieldWithTag ( tif , dp - > tdir_tag ) ;
TIFFReadDirEntryOutputErr ( tif , err , module , fip ? fip - > field_name : " unknown tagname " , 1 ) ;
}
else
{
TIFFSetField ( tif , dp - > tdir_tag , value , value + incrementpersample , value + 2 * incrementpersample ) ;
_TIFFfree ( value ) ;
}
2017-12-08 20:47:54 +08:00
}
2021-03-02 07:17:30 +08:00
break ;
2012-02-29 23:01:28 +08:00
/* BEGIN REV 4.0 COMPATIBILITY */
2021-03-02 07:17:30 +08:00
case TIFFTAG_OSUBFILETYPE :
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
uint16 valueo ;
uint32 value ;
if ( TIFFReadDirEntryShort ( tif , dp , & valueo ) = = TIFFReadDirEntryErrOk )
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
switch ( valueo )
{
case OFILETYPE_REDUCEDIMAGE : value = FILETYPE_REDUCEDIMAGE ; break ;
case OFILETYPE_PAGE : value = FILETYPE_PAGE ; break ;
default : value = 0 ; break ;
}
if ( value ! = 0 )
TIFFSetField ( tif , TIFFTAG_SUBFILETYPE , value ) ;
2017-12-08 20:47:54 +08:00
}
}
2021-03-02 07:17:30 +08:00
break ;
2010-05-12 01:44:00 +08:00
/* END REV 4.0 COMPATIBILITY */
2021-03-02 07:17:30 +08:00
default :
( void ) TIFFFetchNormalTag ( tif , dp , TRUE ) ;
break ;
}
} /* -- if (!dp->tdir_ignore) */
} /* -- for-loop -- */
if ( tif - > tif_mode = = O_RDWR & &
tif - > tif_dir . td_stripoffset_entry . tdir_tag ! = 0 & &
tif - > tif_dir . td_stripoffset_entry . tdir_count = = 0 & &
tif - > tif_dir . td_stripoffset_entry . tdir_type = = 0 & &
tif - > tif_dir . td_stripoffset_entry . tdir_offset . toff_long8 = = 0 & &
tif - > tif_dir . td_stripbytecount_entry . tdir_tag ! = 0 & &
tif - > tif_dir . td_stripbytecount_entry . tdir_count = = 0 & &
tif - > tif_dir . td_stripbytecount_entry . tdir_type = = 0 & &
tif - > tif_dir . td_stripbytecount_entry . tdir_offset . toff_long8 = = 0 )
{
/* Directory typically created with TIFFDeferStrileArrayWriting() */
TIFFSetupStrips ( tif ) ;
}
else if ( ! ( tif - > tif_flags & TIFF_DEFERSTRILELOAD ) )
{
if ( tif - > tif_dir . td_stripoffset_entry . tdir_tag ! = 0 )
{
if ( ! TIFFFetchStripThing ( tif , & ( tif - > tif_dir . td_stripoffset_entry ) ,
tif - > tif_dir . td_nstrips ,
& tif - > tif_dir . td_stripoffset_p ) )
{
goto bad ;
}
}
if ( tif - > tif_dir . td_stripbytecount_entry . tdir_tag ! = 0 )
{
if ( ! TIFFFetchStripThing ( tif , & ( tif - > tif_dir . td_stripbytecount_entry ) ,
tif - > tif_dir . td_nstrips ,
& tif - > tif_dir . td_stripbytecount_p ) )
{
goto bad ;
}
}
}
2017-12-08 20:47:54 +08:00
/*
* OJPEG hack :
* - If a ) compression is OJPEG , and b ) photometric tag is missing ,
* then we consistently find that photometric should be YCbCr
* - If a ) compression is OJPEG , and b ) photometric tag says it ' s RGB ,
* then we consistently find that the buggy implementation of the
* buggy compression scheme matches photometric YCbCr instead .
* - If a ) compression is OJPEG , and b ) bitspersample tag is missing ,
* then we consistently find bitspersample should be 8.
* - If a ) compression is OJPEG , b ) samplesperpixel tag is missing ,
* and c ) photometric is RGB or YCbCr , then we consistently find
* samplesperpixel should be 3
* - If a ) compression is OJPEG , b ) samplesperpixel tag is missing ,
* and c ) photometric is MINISWHITE or MINISBLACK , then we consistently
* find samplesperpixel should be 3
*/
if ( tif - > tif_dir . td_compression = = COMPRESSION_OJPEG )
{
if ( ! TIFFFieldSet ( tif , FIELD_PHOTOMETRIC ) )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Photometric tag is missing, assuming data is YCbCr " ) ;
if ( ! TIFFSetField ( tif , TIFFTAG_PHOTOMETRIC , PHOTOMETRIC_YCBCR ) )
goto bad ;
}
else if ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_RGB )
{
tif - > tif_dir . td_photometric = PHOTOMETRIC_YCBCR ;
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Photometric tag value assumed incorrect, "
" assuming data is YCbCr instead of RGB " ) ;
}
if ( ! TIFFFieldSet ( tif , FIELD_BITSPERSAMPLE ) )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" BitsPerSample tag is missing, assuming 8 bits per sample " ) ;
if ( ! TIFFSetField ( tif , TIFFTAG_BITSPERSAMPLE , 8 ) )
goto bad ;
}
if ( ! TIFFFieldSet ( tif , FIELD_SAMPLESPERPIXEL ) )
{
if ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_RGB )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" SamplesPerPixel tag is missing, "
" assuming correct SamplesPerPixel value is 3 " ) ;
if ( ! TIFFSetField ( tif , TIFFTAG_SAMPLESPERPIXEL , 3 ) )
goto bad ;
}
if ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_YCBCR )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" SamplesPerPixel tag is missing, "
" applying correct SamplesPerPixel value of 3 " ) ;
if ( ! TIFFSetField ( tif , TIFFTAG_SAMPLESPERPIXEL , 3 ) )
goto bad ;
}
else if ( ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_MINISWHITE )
| | ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_MINISBLACK ) )
{
/*
* SamplesPerPixel tag is missing , but is not required
* by spec . Assume correct SamplesPerPixel value of 1.
*/
if ( ! TIFFSetField ( tif , TIFFTAG_SAMPLESPERPIXEL , 1 ) )
goto bad ;
}
}
}
2019-02-12 21:43:58 +08:00
/*
* Make sure all non - color channels are extrasamples .
* If it ' s not the case , define them as such .
*/
color_channels = _TIFFGetMaxColorChannels ( tif - > tif_dir . td_photometric ) ;
if ( color_channels & & tif - > tif_dir . td_samplesperpixel - tif - > tif_dir . td_extrasamples > color_channels ) {
uint16 old_extrasamples ;
uint16 * new_sampleinfo ;
TIFFWarningExt ( tif - > tif_clientdata , module , " Sum of Photometric type-related "
" color channels and ExtraSamples doesn't match SamplesPerPixel. "
" Defining non-color channels as ExtraSamples. " ) ;
old_extrasamples = tif - > tif_dir . td_extrasamples ;
tif - > tif_dir . td_extrasamples = ( uint16 ) ( tif - > tif_dir . td_samplesperpixel - color_channels ) ;
// sampleinfo should contain information relative to these new extra samples
new_sampleinfo = ( uint16 * ) _TIFFcalloc ( tif - > tif_dir . td_extrasamples , sizeof ( uint16 ) ) ;
if ( ! new_sampleinfo ) {
TIFFErrorExt ( tif - > tif_clientdata , module , " Failed to allocate memory for "
" temporary new sampleinfo array (%d 16 bit elements) " ,
tif - > tif_dir . td_extrasamples ) ;
goto bad ;
}
memcpy ( new_sampleinfo , tif - > tif_dir . td_sampleinfo , old_extrasamples * sizeof ( uint16 ) ) ;
_TIFFsetShortArray ( & tif - > tif_dir . td_sampleinfo , new_sampleinfo , tif - > tif_dir . td_extrasamples ) ;
_TIFFfree ( new_sampleinfo ) ;
}
2017-12-08 20:47:54 +08:00
/*
* Verify Palette image has a Colormap .
*/
if ( tif - > tif_dir . td_photometric = = PHOTOMETRIC_PALETTE & &
! TIFFFieldSet ( tif , FIELD_COLORMAP ) ) {
if ( tif - > tif_dir . td_bitspersample > = 8 & & tif - > tif_dir . td_samplesperpixel = = 3 )
tif - > tif_dir . td_photometric = PHOTOMETRIC_RGB ;
else if ( tif - > tif_dir . td_bitspersample > = 8 )
tif - > tif_dir . td_photometric = PHOTOMETRIC_MINISBLACK ;
else {
MissingRequired ( tif , " Colormap " ) ;
goto bad ;
}
}
/*
* OJPEG hack :
* We do no further messing with strip / tile offsets / bytecounts in OJPEG
* TIFFs
*/
if ( tif - > tif_dir . td_compression ! = COMPRESSION_OJPEG )
{
/*
* Attempt to deal with a missing StripByteCounts tag .
*/
if ( ! TIFFFieldSet ( tif , FIELD_STRIPBYTECOUNTS ) ) {
/*
* Some manufacturers violate the spec by not giving
* the size of the strips . In this case , assume there
* is one uncompressed strip of data .
*/
if ( ( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_CONTIG & &
tif - > tif_dir . td_nstrips > 1 ) | |
( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_SEPARATE & &
tif - > tif_dir . td_nstrips ! = ( uint32 ) tif - > tif_dir . td_samplesperpixel ) ) {
MissingRequired ( tif , " StripByteCounts " ) ;
goto bad ;
}
TIFFWarningExt ( tif - > tif_clientdata , module ,
" TIFF directory is missing required "
" \" StripByteCounts \" field, calculating from imagelength " ) ;
if ( EstimateStripByteCounts ( tif , dir , dircount ) < 0 )
goto bad ;
} else if ( tif - > tif_dir . td_nstrips = = 1
& & ! ( tif - > tif_flags & TIFF_ISTILED )
2021-03-02 07:17:30 +08:00
& & ByteCountLooksBad ( tif ) ) {
2017-12-08 20:47:54 +08:00
/*
* XXX : Plexus ( and others ) sometimes give a value of
* zero for a tag when they don ' t know what the
* correct value is ! Try and handle the simple case
* of estimating the size of a one strip image .
*/
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Bogus \" StripByteCounts \" field, ignoring and calculating from imagelength " ) ;
if ( EstimateStripByteCounts ( tif , dir , dircount ) < 0 )
goto bad ;
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
} else if ( ! ( tif - > tif_flags & TIFF_DEFERSTRILELOAD )
& & tif - > tif_dir . td_planarconfig = = PLANARCONFIG_CONTIG
2017-12-08 20:47:54 +08:00
& & tif - > tif_dir . td_nstrips > 2
& & tif - > tif_dir . td_compression = = COMPRESSION_NONE
2021-03-02 07:17:30 +08:00
& & TIFFGetStrileByteCount ( tif , 0 ) ! = TIFFGetStrileByteCount ( tif , 1 )
& & TIFFGetStrileByteCount ( tif , 0 ) ! = 0
& & TIFFGetStrileByteCount ( tif , 1 ) ! = 0 ) {
2017-12-08 20:47:54 +08:00
/*
* XXX : Some vendors fill StripByteCount array with
* absolutely wrong values ( it can be equal to
* StripOffset array , for example ) . Catch this case
* here .
2012-02-29 23:01:28 +08:00
*
* We avoid this check if deferring strile loading
* as it would always force us to load the strip / tile
* information .
2017-12-08 20:47:54 +08:00
*/
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Wrong \" StripByteCounts \" field, ignoring and calculating from imagelength " ) ;
if ( EstimateStripByteCounts ( tif , dir , dircount ) < 0 )
goto bad ;
}
}
if ( dir )
{
_TIFFfree ( dir ) ;
dir = NULL ;
}
if ( ! TIFFFieldSet ( tif , FIELD_MAXSAMPLEVALUE ) )
{
if ( tif - > tif_dir . td_bitspersample > = 16 )
tif - > tif_dir . td_maxsamplevalue = 0xFFFF ;
else
tif - > tif_dir . td_maxsamplevalue = ( uint16 ) ( ( 1L < < tif - > tif_dir . td_bitspersample ) - 1 ) ;
}
2021-03-02 07:17:30 +08:00
# ifdef STRIPBYTECOUNTSORTED_UNUSED
2017-12-08 20:47:54 +08:00
/*
* XXX : We can optimize checking for the strip bounds using the sorted
* bytecounts array . See also comments for TIFFAppendToStrip ( )
* function in tif_write . c .
*/
2021-03-02 07:17:30 +08:00
if ( ! ( tif - > tif_flags & TIFF_DEFERSTRILELOAD ) & & tif - > tif_dir . td_nstrips > 1 ) {
2017-12-08 20:47:54 +08:00
uint32 strip ;
tif - > tif_dir . td_stripbytecountsorted = 1 ;
for ( strip = 1 ; strip < tif - > tif_dir . td_nstrips ; strip + + ) {
2021-03-02 07:17:30 +08:00
if ( TIFFGetStrileOffset ( tif , strip - 1 ) >
TIFFGetStrileOffset ( tif , strip ) ) {
2017-12-08 20:47:54 +08:00
tif - > tif_dir . td_stripbytecountsorted = 0 ;
break ;
}
}
}
2021-03-02 07:17:30 +08:00
# endif
2017-12-08 20:47:54 +08:00
/*
* An opportunity for compression mode dependent tag fixup
*/
( * tif - > tif_fixuptags ) ( tif ) ;
/*
* Some manufacturers make life difficult by writing
* large amounts of uncompressed data as a single strip .
* This is contrary to the recommendations of the spec .
* The following makes an attempt at breaking such images
* into strips closer to the recommended 8 k bytes . A
* side effect , however , is that the RowsPerStrip tag
* value may be changed .
*/
if ( ( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_CONTIG ) & &
( tif - > tif_dir . td_nstrips = = 1 ) & &
( tif - > tif_dir . td_compression = = COMPRESSION_NONE ) & &
( ( tif - > tif_flags & ( TIFF_STRIPCHOP | TIFF_ISTILED ) ) = = TIFF_STRIPCHOP ) )
2021-03-02 07:17:30 +08:00
{
ChopUpSingleUncompressedStrip ( tif ) ;
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
/* There are also uncompressed striped files with strips larger than */
2020-03-24 02:43:45 +08:00
/* 2 GB, which make them unfriendly with a lot of code. If possible, */
/* try to expose smaller "virtual" strips. */
if ( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_CONTIG & &
tif - > tif_dir . td_compression = = COMPRESSION_NONE & &
( tif - > tif_flags & ( TIFF_STRIPCHOP | TIFF_ISTILED ) ) = = TIFF_STRIPCHOP & &
TIFFStripSize64 ( tif ) > 0x7FFFFFFFUL )
{
TryChopUpUncompressedBigTiff ( tif ) ;
}
2012-02-29 23:01:28 +08:00
/*
2017-12-08 20:47:54 +08:00
* Clear the dirty directory flag .
2012-02-29 23:01:28 +08:00
*/
2017-12-08 20:47:54 +08:00
tif - > tif_flags & = ~ TIFF_DIRTYDIRECT ;
tif - > tif_flags & = ~ TIFF_DIRTYSTRIP ;
/*
* Reinitialize i / o since we are starting on a new directory .
*/
tif - > tif_row = ( uint32 ) - 1 ;
tif - > tif_curstrip = ( uint32 ) - 1 ;
tif - > tif_col = ( uint32 ) - 1 ;
tif - > tif_curtile = ( uint32 ) - 1 ;
tif - > tif_tilesize = ( tmsize_t ) - 1 ;
tif - > tif_scanlinesize = TIFFScanlineSize ( tif ) ;
if ( ! tif - > tif_scanlinesize ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot handle zero scanline size " ) ;
return ( 0 ) ;
}
if ( isTiled ( tif ) ) {
tif - > tif_tilesize = TIFFTileSize ( tif ) ;
if ( ! tif - > tif_tilesize ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot handle zero tile size " ) ;
return ( 0 ) ;
}
} else {
if ( ! TIFFStripSize ( tif ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot handle zero strip size " ) ;
return ( 0 ) ;
}
}
return ( 1 ) ;
2010-05-12 01:44:00 +08:00
bad :
2017-12-08 20:47:54 +08:00
if ( dir )
_TIFFfree ( dir ) ;
return ( 0 ) ;
2010-05-12 01:44:00 +08:00
}
2012-02-29 23:01:28 +08:00
static void
TIFFReadDirectoryCheckOrder ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount )
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFReadDirectoryCheckOrder " ;
2023-07-13 18:21:21 +08:00
uint32 m ;
2017-12-08 20:47:54 +08:00
uint16 n ;
TIFFDirEntry * o ;
m = 0 ;
for ( n = 0 , o = dir ; n < dircount ; n + + , o + + )
{
if ( o - > tdir_tag < m )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Invalid TIFF directory; tags are not sorted in ascending order " ) ;
break ;
}
m = o - > tdir_tag + 1 ;
}
2012-02-29 23:01:28 +08:00
}
2010-07-16 20:54:53 +08:00
static TIFFDirEntry *
2012-02-29 23:01:28 +08:00
TIFFReadDirectoryFindEntry ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount , uint16 tagid )
2010-07-16 20:54:53 +08:00
{
2017-12-08 20:47:54 +08:00
TIFFDirEntry * m ;
uint16 n ;
( void ) tif ;
for ( m = dir , n = 0 ; n < dircount ; m + + , n + + )
{
if ( m - > tdir_tag = = tagid )
return ( m ) ;
}
return ( 0 ) ;
2010-07-16 20:54:53 +08:00
}
2017-12-08 20:47:54 +08:00
static void
TIFFReadDirectoryFindFieldInfo ( TIFF * tif , uint16 tagid , uint32 * fii )
{
int32 ma , mb , mc ;
ma = - 1 ;
mc = ( int32 ) tif - > tif_nfields ;
while ( 1 )
{
if ( ma + 1 = = mc )
{
* fii = FAILED_FII ;
return ;
}
mb = ( ma + mc ) / 2 ;
if ( tif - > tif_fields [ mb ] - > field_tag = = ( uint32 ) tagid )
break ;
if ( tif - > tif_fields [ mb ] - > field_tag < ( uint32 ) tagid )
ma = mb ;
else
mc = mb ;
}
while ( 1 )
{
if ( mb = = 0 )
break ;
if ( tif - > tif_fields [ mb - 1 ] - > field_tag ! = ( uint32 ) tagid )
break ;
mb - - ;
}
* fii = mb ;
2012-02-29 23:01:28 +08:00
}
2010-07-16 20:54:53 +08:00
/*
2017-12-08 20:47:54 +08:00
* Read custom directory from the arbitrary offset .
2010-07-16 20:54:53 +08:00
* The code is very similar to TIFFReadDirectory ( ) .
*/
int
TIFFReadCustomDirectory ( TIFF * tif , toff_t diroff ,
2017-12-08 20:47:54 +08:00
const TIFFFieldArray * infoarray )
2010-07-16 20:54:53 +08:00
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFReadCustomDirectory " ;
TIFFDirEntry * dir ;
uint16 dircount ;
TIFFDirEntry * dp ;
uint16 di ;
const TIFFField * fip ;
uint32 fii ;
2021-03-02 07:17:30 +08:00
( * tif - > tif_cleanup ) ( tif ) ; /* cleanup any previous compression state */
2017-12-08 20:47:54 +08:00
_TIFFSetupFields ( tif , infoarray ) ;
dircount = TIFFFetchDirectory ( tif , diroff , & dir , NULL ) ;
if ( ! dircount )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Failed to read custom directory at offset " TIFF_UINT64_FORMAT , diroff ) ;
return 0 ;
}
TIFFFreeDirectory ( tif ) ;
_TIFFmemset ( & tif - > tif_dir , 0 , sizeof ( TIFFDirectory ) ) ;
TIFFReadDirectoryCheckOrder ( tif , dir , dircount ) ;
for ( di = 0 , dp = dir ; di < dircount ; di + + , dp + + )
{
TIFFReadDirectoryFindFieldInfo ( tif , dp - > tdir_tag , & fii ) ;
if ( fii = = FAILED_FII )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Unknown field with tag %d (0x%x) encountered " ,
dp - > tdir_tag , dp - > tdir_tag ) ;
if ( ! _TIFFMergeFields ( tif , _TIFFCreateAnonField ( tif ,
dp - > tdir_tag ,
( TIFFDataType ) dp - > tdir_type ) ,
1 ) ) {
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Registering anonymous field with tag %d (0x%x) failed " ,
dp - > tdir_tag , dp - > tdir_tag ) ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
} else {
TIFFReadDirectoryFindFieldInfo ( tif , dp - > tdir_tag , & fii ) ;
assert ( fii ! = FAILED_FII ) ;
}
}
2021-03-02 07:17:30 +08:00
if ( ! dp - > tdir_ignore )
2017-12-08 20:47:54 +08:00
{
fip = tif - > tif_fields [ fii ] ;
if ( fip - > field_bit = = FIELD_IGNORE )
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
else
{
/* check data type */
while ( ( fip - > field_type ! = TIFF_ANY ) & & ( fip - > field_type ! = dp - > tdir_type ) )
{
fii + + ;
if ( ( fii = = tif - > tif_nfields ) | |
( tif - > tif_fields [ fii ] - > field_tag ! = ( uint32 ) dp - > tdir_tag ) )
{
fii = 0xFFFF ;
break ;
}
fip = tif - > tif_fields [ fii ] ;
}
if ( fii = = 0xFFFF )
{
TIFFWarningExt ( tif - > tif_clientdata , module ,
" Wrong data type %d for \" %s \" ; tag ignored " ,
dp - > tdir_type , fip - > field_name ) ;
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
}
else
{
/* check count if known in advance */
if ( ( fip - > field_readcount ! = TIFF_VARIABLE ) & &
( fip - > field_readcount ! = TIFF_VARIABLE2 ) )
{
uint32 expected ;
if ( fip - > field_readcount = = TIFF_SPP )
expected = ( uint32 ) tif - > tif_dir . td_samplesperpixel ;
else
expected = ( uint32 ) fip - > field_readcount ;
if ( ! CheckDirCount ( tif , dp , expected ) )
2021-03-02 07:17:30 +08:00
dp - > tdir_ignore = TRUE ;
2017-12-08 20:47:54 +08:00
}
}
}
2021-03-02 07:17:30 +08:00
if ( ! dp - > tdir_ignore ) {
switch ( dp - > tdir_tag )
{
case EXIFTAG_SUBJECTDISTANCE :
( void ) TIFFFetchSubjectDistance ( tif , dp ) ;
break ;
default :
( void ) TIFFFetchNormalTag ( tif , dp , TRUE ) ;
break ;
}
} /*-- if (!dp->tdir_ignore) */
2017-12-08 20:47:54 +08:00
}
}
if ( dir )
_TIFFfree ( dir ) ;
return 1 ;
2010-07-16 20:54:53 +08:00
}
/*
* EXIF is important special case of custom IFD , so we have a special
* function to read it .
*/
int
TIFFReadEXIFDirectory ( TIFF * tif , toff_t diroff )
{
2017-12-08 20:47:54 +08:00
const TIFFFieldArray * exifFieldArray ;
exifFieldArray = _TIFFGetExifFields ( ) ;
return TIFFReadCustomDirectory ( tif , diroff , exifFieldArray ) ;
2010-07-16 20:54:53 +08:00
}
2021-03-02 07:17:30 +08:00
/*
* - - : EXIF - GPS custom directory reading as another special case of custom IFD .
*/
int
TIFFReadGPSDirectory ( TIFF * tif , toff_t diroff )
{
const TIFFFieldArray * gpsFieldArray ;
gpsFieldArray = _TIFFGetGpsFields ( ) ;
return TIFFReadCustomDirectory ( tif , diroff , gpsFieldArray ) ;
}
2010-05-12 01:44:00 +08:00
static int
EstimateStripByteCounts ( TIFF * tif , TIFFDirEntry * dir , uint16 dircount )
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " EstimateStripByteCounts " ;
2010-05-12 01:44:00 +08:00
2017-12-08 20:47:54 +08:00
TIFFDirEntry * dp ;
TIFFDirectory * td = & tif - > tif_dir ;
uint32 strip ;
2010-05-12 01:44:00 +08:00
2017-12-08 20:47:54 +08:00
/* Do not try to load stripbytecount as we will compute it */
if ( ! _TIFFFillStrilesInternal ( tif , 0 ) )
return - 1 ;
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
if ( td - > td_stripbytecount_p )
_TIFFfree ( td - > td_stripbytecount_p ) ;
td - > td_stripbytecount_p = ( uint64 * )
2017-12-08 20:47:54 +08:00
_TIFFCheckMalloc ( tif , td - > td_nstrips , sizeof ( uint64 ) ,
" for \" StripByteCounts \" array " ) ;
2021-03-02 07:17:30 +08:00
if ( td - > td_stripbytecount_p = = NULL )
2010-07-16 20:54:53 +08:00
return - 1 ;
2017-12-08 20:47:54 +08:00
if ( td - > td_compression ! = COMPRESSION_NONE ) {
uint64 space ;
uint64 filesize ;
uint16 n ;
filesize = TIFFGetFileSize ( tif ) ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
space = sizeof ( TIFFHeaderClassic ) + 2 + dircount * 12 + 4 ;
else
space = sizeof ( TIFFHeaderBig ) + 8 + dircount * 20 + 8 ;
/* calculate amount of space used by indirect values */
for ( dp = dir , n = dircount ; n > 0 ; n - - , dp + + )
{
uint32 typewidth ;
uint64 datasize ;
typewidth = TIFFDataWidth ( ( TIFFDataType ) dp - > tdir_type ) ;
if ( typewidth = = 0 ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot determine size of unknown tag type %d " ,
dp - > tdir_type ) ;
return - 1 ;
}
2021-03-02 07:17:30 +08:00
if ( dp - > tdir_count > TIFF_UINT64_MAX / typewidth )
return - 1 ;
2017-12-08 20:47:54 +08:00
datasize = ( uint64 ) typewidth * dp - > tdir_count ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
if ( datasize < = 4 )
datasize = 0 ;
}
else
{
if ( datasize < = 8 )
datasize = 0 ;
}
2021-03-02 07:17:30 +08:00
if ( space > TIFF_UINT64_MAX - datasize )
return - 1 ;
2017-12-08 20:47:54 +08:00
space + = datasize ;
}
if ( filesize < space )
/* we should perhaps return in error ? */
space = filesize ;
else
space = filesize - space ;
if ( td - > td_planarconfig = = PLANARCONFIG_SEPARATE )
space / = td - > td_samplesperpixel ;
for ( strip = 0 ; strip < td - > td_nstrips ; strip + + )
2021-03-02 07:17:30 +08:00
td - > td_stripbytecount_p [ strip ] = space ;
2017-12-08 20:47:54 +08:00
/*
* This gross hack handles the case were the offset to
* the last strip is past the place where we think the strip
* should begin . Since a strip of data must be contiguous ,
* it ' s safe to assume that we ' ve overestimated the amount
* of data in the strip and trim this number back accordingly .
*/
strip - - ;
2021-03-02 07:17:30 +08:00
if ( td - > td_stripoffset_p [ strip ] > TIFF_UINT64_MAX - td - > td_stripbytecount_p [ strip ] )
return - 1 ;
if ( td - > td_stripoffset_p [ strip ] + td - > td_stripbytecount_p [ strip ] > filesize ) {
if ( td - > td_stripoffset_p [ strip ] > = filesize ) {
/* Not sure what we should in that case... */
td - > td_stripbytecount_p [ strip ] = 0 ;
} else {
td - > td_stripbytecount_p [ strip ] = filesize - td - > td_stripoffset_p [ strip ] ;
}
}
2017-12-08 20:47:54 +08:00
} else if ( isTiled ( tif ) ) {
uint64 bytespertile = TIFFTileSize64 ( tif ) ;
for ( strip = 0 ; strip < td - > td_nstrips ; strip + + )
2021-03-02 07:17:30 +08:00
td - > td_stripbytecount_p [ strip ] = bytespertile ;
2017-12-08 20:47:54 +08:00
} else {
uint64 rowbytes = TIFFScanlineSize64 ( tif ) ;
uint32 rowsperstrip = td - > td_imagelength / td - > td_stripsperimage ;
for ( strip = 0 ; strip < td - > td_nstrips ; strip + + )
2021-03-02 07:17:30 +08:00
{
if ( rowbytes > 0 & & rowsperstrip > TIFF_UINT64_MAX / rowbytes )
return - 1 ;
td - > td_stripbytecount_p [ strip ] = rowbytes * rowsperstrip ;
}
2017-12-08 20:47:54 +08:00
}
TIFFSetFieldBit ( tif , FIELD_STRIPBYTECOUNTS ) ;
if ( ! TIFFFieldSet ( tif , FIELD_ROWSPERSTRIP ) )
td - > td_rowsperstrip = td - > td_imagelength ;
return 1 ;
2010-05-12 01:44:00 +08:00
}
static void
MissingRequired ( TIFF * tif , const char * tagname )
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " MissingRequired " ;
2010-05-12 01:44:00 +08:00
2017-12-08 20:47:54 +08:00
TIFFErrorExt ( tif - > tif_clientdata , module ,
" TIFF directory is missing required \" %s \" field " ,
tagname ) ;
2010-05-12 01:44:00 +08:00
}
/*
2010-07-16 20:54:53 +08:00
* Check the directory offset against the list of already seen directory
* offsets . This is a trick to prevent IFD looping . The one can create TIFF
* file with looped directory pointers . We will maintain a list of already
* seen directories and check every IFD offset against that list .
*/
static int
2012-02-29 23:01:28 +08:00
TIFFCheckDirOffset ( TIFF * tif , uint64 diroff )
2010-07-16 20:54:53 +08:00
{
2017-12-08 20:47:54 +08:00
uint16 n ;
if ( diroff = = 0 ) /* no more directories */
return 0 ;
if ( tif - > tif_dirnumber = = 65535 ) {
TIFFErrorExt ( tif - > tif_clientdata , " TIFFCheckDirOffset " ,
" Cannot handle more than 65535 TIFF directories " ) ;
return 0 ;
}
for ( n = 0 ; n < tif - > tif_dirnumber & & tif - > tif_dirlist ; n + + ) {
if ( tif - > tif_dirlist [ n ] = = diroff )
return 0 ;
}
tif - > tif_dirnumber + + ;
if ( tif - > tif_dirlist = = NULL | | tif - > tif_dirnumber > tif - > tif_dirlistsize ) {
uint64 * new_dirlist ;
/*
* XXX : Reduce memory allocation granularity of the dirlist
* array .
*/
new_dirlist = ( uint64 * ) _TIFFCheckRealloc ( tif , tif - > tif_dirlist ,
tif - > tif_dirnumber , 2 * sizeof ( uint64 ) , " for IFD list " ) ;
if ( ! new_dirlist )
return 0 ;
if ( tif - > tif_dirnumber > = 32768 )
tif - > tif_dirlistsize = 65535 ;
else
tif - > tif_dirlistsize = 2 * tif - > tif_dirnumber ;
tif - > tif_dirlist = new_dirlist ;
}
tif - > tif_dirlist [ tif - > tif_dirnumber - 1 ] = diroff ;
return 1 ;
2010-07-16 20:54:53 +08:00
}
/*
* Check the count field of a directory entry against a known value . The
* caller is expected to skip / ignore the tag if there is a mismatch .
2010-05-12 01:44:00 +08:00
*/
static int
CheckDirCount ( TIFF * tif , TIFFDirEntry * dir , uint32 count )
{
2017-12-08 20:47:54 +08:00
if ( ( uint64 ) count > dir - > tdir_count ) {
const TIFFField * fip = TIFFFieldWithTag ( tif , dir - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , tif - > tif_name ,
" incorrect count for field \" %s \" ( " TIFF_UINT64_FORMAT " , expecting %u); tag ignored " ,
fip ? fip - > field_name : " unknown tagname " ,
dir - > tdir_count , count ) ;
return ( 0 ) ;
} else if ( ( uint64 ) count < dir - > tdir_count ) {
const TIFFField * fip = TIFFFieldWithTag ( tif , dir - > tdir_tag ) ;
TIFFWarningExt ( tif - > tif_clientdata , tif - > tif_name ,
" incorrect count for field \" %s \" ( " TIFF_UINT64_FORMAT " , expecting %u); tag trimmed " ,
fip ? fip - > field_name : " unknown tagname " ,
dir - > tdir_count , count ) ;
dir - > tdir_count = count ;
return ( 1 ) ;
}
return ( 1 ) ;
2010-05-12 01:44:00 +08:00
}
2010-07-16 20:54:53 +08:00
/*
* Read IFD structure from the specified offset . If the pointer to
* nextdiroff variable has been specified , read it too . Function returns a
* number of fields in the directory or 0 if failed .
*/
static uint16
2012-02-29 23:01:28 +08:00
TIFFFetchDirectory ( TIFF * tif , uint64 diroff , TIFFDirEntry * * pdir ,
uint64 * nextdiroff )
2010-07-16 20:54:53 +08:00
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFFetchDirectory " ;
void * origdir ;
uint16 dircount16 ;
uint32 dirsize ;
TIFFDirEntry * dir ;
uint8 * ma ;
TIFFDirEntry * mb ;
uint16 n ;
assert ( pdir ) ;
tif - > tif_diroff = diroff ;
if ( nextdiroff )
* nextdiroff = 0 ;
if ( ! isMapped ( tif ) ) {
if ( ! SeekOK ( tif , tif - > tif_diroff ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" %s: Seek error accessing TIFF directory " ,
tif - > tif_name ) ;
return 0 ;
}
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
if ( ! ReadOK ( tif , & dircount16 , sizeof ( uint16 ) ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" %s: Can not read TIFF directory count " ,
tif - > tif_name ) ;
return 0 ;
}
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( & dircount16 ) ;
if ( dircount16 > 4096 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on directory count failed, this is probably not a valid IFD offset " ) ;
return 0 ;
}
dirsize = 12 ;
} else {
uint64 dircount64 ;
if ( ! ReadOK ( tif , & dircount64 , sizeof ( uint64 ) ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" %s: Can not read TIFF directory count " ,
tif - > tif_name ) ;
return 0 ;
}
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( & dircount64 ) ;
if ( dircount64 > 4096 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on directory count failed, this is probably not a valid IFD offset " ) ;
return 0 ;
}
dircount16 = ( uint16 ) dircount64 ;
dirsize = 20 ;
}
origdir = _TIFFCheckMalloc ( tif , dircount16 ,
dirsize , " to read TIFF directory " ) ;
if ( origdir = = NULL )
return 0 ;
if ( ! ReadOK ( tif , origdir , ( tmsize_t ) ( dircount16 * dirsize ) ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" %.100s: Can not read TIFF directory " ,
tif - > tif_name ) ;
_TIFFfree ( origdir ) ;
return 0 ;
}
/*
* Read offset to next directory for sequential scans if
* needed .
*/
if ( nextdiroff )
{
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
uint32 nextdiroff32 ;
if ( ! ReadOK ( tif , & nextdiroff32 , sizeof ( uint32 ) ) )
nextdiroff32 = 0 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & nextdiroff32 ) ;
* nextdiroff = nextdiroff32 ;
} else {
if ( ! ReadOK ( tif , nextdiroff , sizeof ( uint64 ) ) )
* nextdiroff = 0 ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( nextdiroff ) ;
}
}
} else {
tmsize_t m ;
2021-03-02 07:17:30 +08:00
tmsize_t off ;
if ( tif - > tif_diroff > ( uint64 ) TIFF_INT64_MAX )
2017-12-08 20:47:54 +08:00
{
TIFFErrorExt ( tif - > tif_clientdata , module , " Can not read TIFF directory count " ) ;
return ( 0 ) ;
}
2021-03-02 07:17:30 +08:00
off = ( tmsize_t ) tif - > tif_diroff ;
2017-12-08 20:47:54 +08:00
/*
* Check for integer overflow when validating the dir_off ,
* otherwise a very high offset may cause an OOB read and
* crash the client . Make two comparisons instead of
*
* off + sizeof ( uint16 ) > tif - > tif_size
*
* to avoid overflow .
*/
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
m = off + sizeof ( uint16 ) ;
if ( ( m < off ) | | ( m < ( tmsize_t ) sizeof ( uint16 ) ) | | ( m > tif - > tif_size ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Can not read TIFF directory count " ) ;
return 0 ;
} else {
_TIFFmemcpy ( & dircount16 , tif - > tif_base + off ,
sizeof ( uint16 ) ) ;
}
off + = sizeof ( uint16 ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( & dircount16 ) ;
if ( dircount16 > 4096 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on directory count failed, this is probably not a valid IFD offset " ) ;
return 0 ;
}
dirsize = 12 ;
}
else
{
uint64 dircount64 ;
m = off + sizeof ( uint64 ) ;
if ( ( m < off ) | | ( m < ( tmsize_t ) sizeof ( uint64 ) ) | | ( m > tif - > tif_size ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Can not read TIFF directory count " ) ;
return 0 ;
} else {
_TIFFmemcpy ( & dircount64 , tif - > tif_base + off ,
sizeof ( uint64 ) ) ;
}
off + = sizeof ( uint64 ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( & dircount64 ) ;
if ( dircount64 > 4096 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on directory count failed, this is probably not a valid IFD offset " ) ;
return 0 ;
}
dircount16 = ( uint16 ) dircount64 ;
dirsize = 20 ;
}
if ( dircount16 = = 0 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Sanity check on directory count failed, zero tag directories not supported " ) ;
return 0 ;
}
origdir = _TIFFCheckMalloc ( tif , dircount16 ,
dirsize ,
" to read TIFF directory " ) ;
if ( origdir = = NULL )
return 0 ;
m = off + dircount16 * dirsize ;
if ( ( m < off ) | | ( m < ( tmsize_t ) ( dircount16 * dirsize ) ) | | ( m > tif - > tif_size ) ) {
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Can not read TIFF directory " ) ;
_TIFFfree ( origdir ) ;
return 0 ;
} else {
_TIFFmemcpy ( origdir , tif - > tif_base + off ,
dircount16 * dirsize ) ;
}
if ( nextdiroff ) {
off + = dircount16 * dirsize ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
uint32 nextdiroff32 ;
m = off + sizeof ( uint32 ) ;
if ( ( m < off ) | | ( m < ( tmsize_t ) sizeof ( uint32 ) ) | | ( m > tif - > tif_size ) )
nextdiroff32 = 0 ;
else
_TIFFmemcpy ( & nextdiroff32 , tif - > tif_base + off ,
sizeof ( uint32 ) ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & nextdiroff32 ) ;
* nextdiroff = nextdiroff32 ;
}
else
{
m = off + sizeof ( uint64 ) ;
if ( ( m < off ) | | ( m < ( tmsize_t ) sizeof ( uint64 ) ) | | ( m > tif - > tif_size ) )
* nextdiroff = 0 ;
else
_TIFFmemcpy ( nextdiroff , tif - > tif_base + off ,
sizeof ( uint64 ) ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( nextdiroff ) ;
}
}
}
dir = ( TIFFDirEntry * ) _TIFFCheckMalloc ( tif , dircount16 ,
sizeof ( TIFFDirEntry ) ,
" to read TIFF directory " ) ;
if ( dir = = 0 )
{
_TIFFfree ( origdir ) ;
return 0 ;
}
ma = ( uint8 * ) origdir ;
mb = dir ;
for ( n = 0 ; n < dircount16 ; n + + )
{
2021-03-02 07:17:30 +08:00
mb - > tdir_ignore = FALSE ;
2017-12-08 20:47:54 +08:00
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
mb - > tdir_tag = * ( uint16 * ) ma ;
ma + = sizeof ( uint16 ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabShort ( ( uint16 * ) ma ) ;
mb - > tdir_type = * ( uint16 * ) ma ;
ma + = sizeof ( uint16 ) ;
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( ( uint32 * ) ma ) ;
mb - > tdir_count = ( uint64 ) ( * ( uint32 * ) ma ) ;
ma + = sizeof ( uint32 ) ;
2021-03-02 07:17:30 +08:00
mb - > tdir_offset . toff_long8 = 0 ;
2017-12-08 20:47:54 +08:00
* ( uint32 * ) ( & mb - > tdir_offset ) = * ( uint32 * ) ma ;
ma + = sizeof ( uint32 ) ;
}
else
{
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong8 ( ( uint64 * ) ma ) ;
2012-02-29 23:01:28 +08:00
mb - > tdir_count = TIFFReadUInt64 ( ma ) ;
2017-12-08 20:47:54 +08:00
ma + = sizeof ( uint64 ) ;
mb - > tdir_offset . toff_long8 = TIFFReadUInt64 ( ma ) ;
ma + = sizeof ( uint64 ) ;
}
mb + + ;
}
_TIFFfree ( origdir ) ;
* pdir = dir ;
return dircount16 ;
2010-05-12 01:44:00 +08:00
}
/*
2012-02-29 23:01:28 +08:00
* Fetch a tag that is not handled by special case code .
2010-05-12 01:44:00 +08:00
*/
static int
2012-02-29 23:01:28 +08:00
TIFFFetchNormalTag ( TIFF * tif , TIFFDirEntry * dp , int recover )
2010-05-12 01:44:00 +08:00
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFFetchNormalTag " ;
enum TIFFReadDirEntryErr err ;
uint32 fii ;
const TIFFField * fip = NULL ;
TIFFReadDirectoryFindFieldInfo ( tif , dp - > tdir_tag , & fii ) ;
2012-02-29 23:01:28 +08:00
if ( fii = = FAILED_FII )
{
TIFFErrorExt ( tif - > tif_clientdata , " TIFFFetchNormalTag " ,
" No definition found for tag %d " ,
dp - > tdir_tag ) ;
return 0 ;
}
2017-12-08 20:47:54 +08:00
fip = tif - > tif_fields [ fii ] ;
assert ( fip ! = NULL ) ; /* should not happen */
assert ( fip - > set_field_type ! = TIFF_SETGET_OTHER ) ; /* if so, we shouldn't arrive here but deal with this in specialized code */
assert ( fip - > set_field_type ! = TIFF_SETGET_INT ) ; /* if so, we shouldn't arrive here as this is only the case for pseudo-tags */
err = TIFFReadDirEntryErrOk ;
switch ( fip - > set_field_type )
{
case TIFF_SETGET_UNDEFINED :
break ;
case TIFF_SETGET_ASCII :
{
uint8 * data ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
2019-02-12 21:43:58 +08:00
uint32 mb = 0 ;
2017-12-08 20:47:54 +08:00
int n ;
2019-02-12 21:43:58 +08:00
if ( data ! = NULL )
2017-12-08 20:47:54 +08:00
{
2019-02-12 21:43:58 +08:00
uint8 * ma = data ;
while ( mb < ( uint32 ) dp - > tdir_count )
{
if ( * ma = = 0 )
break ;
ma + + ;
mb + + ;
}
2017-12-08 20:47:54 +08:00
}
if ( mb + 1 < ( uint32 ) dp - > tdir_count )
TIFFWarningExt ( tif - > tif_clientdata , module , " ASCII value for tag \" %s \" contains null byte in value; value incorrectly truncated during reading due to implementation limitations " , fip - > field_name ) ;
else if ( mb + 1 > ( uint32 ) dp - > tdir_count )
{
uint8 * o ;
TIFFWarningExt ( tif - > tif_clientdata , module , " ASCII value for tag \" %s \" does not end in null byte " , fip - > field_name ) ;
if ( ( uint32 ) dp - > tdir_count + 1 ! = dp - > tdir_count + 1 )
o = NULL ;
else
o = _TIFFmalloc ( ( uint32 ) dp - > tdir_count + 1 ) ;
if ( o = = NULL )
{
if ( data ! = NULL )
_TIFFfree ( data ) ;
return ( 0 ) ;
}
_TIFFmemcpy ( o , data , ( uint32 ) dp - > tdir_count ) ;
o [ ( uint32 ) dp - > tdir_count ] = 0 ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
data = o ;
}
n = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! n )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_UINT8 :
{
uint8 data = 0 ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryByte ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_UINT16 :
{
uint16 data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryShort ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_UINT32 :
{
uint32 data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryLong ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_UINT64 :
{
uint64 data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryLong8 ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_FLOAT :
{
float data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryFloat ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_DOUBLE :
{
double data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryDouble ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_IFD8 :
{
uint64 data ;
assert ( fip - > field_readcount = = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
err = TIFFReadDirEntryIfd8 ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
if ( ! TIFFSetField ( tif , dp - > tdir_tag , data ) )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_UINT16_PAIR :
{
uint16 * data ;
assert ( fip - > field_readcount = = 2 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = 2 ) {
TIFFWarningExt ( tif - > tif_clientdata , module ,
" incorrect count for field \" %s \" , expected 2, got %d " ,
fip - > field_name , ( int ) dp - > tdir_count ) ;
return ( 0 ) ;
}
err = TIFFReadDirEntryShortArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
2021-03-02 07:17:30 +08:00
assert ( data ) ; /* avoid CLang static Analyzer false positive */
2017-12-08 20:47:54 +08:00
m = TIFFSetField ( tif , dp - > tdir_tag , data [ 0 ] , data [ 1 ] ) ;
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C0_UINT8 :
{
uint8 * data ;
assert ( fip - > field_readcount > = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = ( uint64 ) fip - > field_readcount ) {
TIFFWarningExt ( tif - > tif_clientdata , module ,
" incorrect count for field \" %s \" , expected %d, got %d " ,
fip - > field_name , ( int ) fip - > field_readcount , ( int ) dp - > tdir_count ) ;
return 0 ;
}
else
{
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C0_UINT16 :
{
uint16 * data ;
assert ( fip - > field_readcount > = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = ( uint64 ) fip - > field_readcount )
2012-02-29 23:01:28 +08:00
/* corrupt file */ ;
2017-12-08 20:47:54 +08:00
else
{
err = TIFFReadDirEntryShortArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C0_UINT32 :
{
uint32 * data ;
assert ( fip - > field_readcount > = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = ( uint64 ) fip - > field_readcount )
2012-02-29 23:01:28 +08:00
/* corrupt file */ ;
2017-12-08 20:47:54 +08:00
else
{
err = TIFFReadDirEntryLongArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C0_FLOAT :
{
float * data ;
assert ( fip - > field_readcount > = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = ( uint64 ) fip - > field_readcount )
2021-03-02 07:17:30 +08:00
/* corrupt file */ ;
2017-12-08 20:47:54 +08:00
else
{
err = TIFFReadDirEntryFloatArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
2021-03-02 07:17:30 +08:00
/*--: Rational2Double: Extend for Double Arrays and Rational-Arrays read into Double-Arrays. */
case TIFF_SETGET_C0_DOUBLE :
{
double * data ;
assert ( fip - > field_readcount > = 1 ) ;
assert ( fip - > field_passcount = = 0 ) ;
if ( dp - > tdir_count ! = ( uint64 ) fip - > field_readcount )
/* corrupt file */ ;
else
{
err = TIFFReadDirEntryDoubleArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
2017-12-08 20:47:54 +08:00
case TIFF_SETGET_C16_ASCII :
{
uint8 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
2019-02-12 21:43:58 +08:00
if ( data ! = 0 & & dp - > tdir_count > 0 & & data [ dp - > tdir_count - 1 ] ! = ' \0 ' )
{
TIFFWarningExt ( tif - > tif_clientdata , module , " ASCII value for tag \" %s \" does not end in null byte. Forcing it to be null " , fip - > field_name ) ;
data [ dp - > tdir_count - 1 ] = ' \0 ' ;
}
2017-12-08 20:47:54 +08:00
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_UINT8 :
{
uint8 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_UINT16 :
{
uint16 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryShortArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_UINT32 :
{
uint32 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryLongArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_UINT64 :
{
uint64 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryLong8Array ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_FLOAT :
{
float * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryFloatArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_DOUBLE :
{
double * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryDoubleArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C16_IFD8 :
{
uint64 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE ) ;
assert ( fip - > field_passcount = = 1 ) ;
if ( dp - > tdir_count > 0xFFFF )
err = TIFFReadDirEntryErrCount ;
else
{
err = TIFFReadDirEntryIfd8Array ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint16 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
}
break ;
case TIFF_SETGET_C32_ASCII :
{
uint8 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
2019-02-12 21:43:58 +08:00
if ( data ! = 0 & & dp - > tdir_count > 0 & & data [ dp - > tdir_count - 1 ] ! = ' \0 ' )
{
TIFFWarningExt ( tif - > tif_clientdata , module , " ASCII value for tag \" %s \" does not end in null byte. Forcing it to be null " , fip - > field_name ) ;
data [ dp - > tdir_count - 1 ] = ' \0 ' ;
}
2017-12-08 20:47:54 +08:00
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_UINT8 :
{
uint8 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryByteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_SINT8 :
{
int8 * data = NULL ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntrySbyteArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_UINT16 :
{
uint16 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryShortArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_SINT16 :
{
int16 * data = NULL ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntrySshortArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_UINT32 :
{
uint32 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryLongArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_SINT32 :
{
int32 * data = NULL ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntrySlongArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_UINT64 :
{
uint64 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryLong8Array ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_SINT64 :
{
int64 * data = NULL ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntrySlong8Array ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_FLOAT :
{
float * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryFloatArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_DOUBLE :
{
double * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryDoubleArray ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
case TIFF_SETGET_C32_IFD8 :
{
uint64 * data ;
assert ( fip - > field_readcount = = TIFF_VARIABLE2 ) ;
assert ( fip - > field_passcount = = 1 ) ;
err = TIFFReadDirEntryIfd8Array ( tif , dp , & data ) ;
if ( err = = TIFFReadDirEntryErrOk )
{
int m ;
m = TIFFSetField ( tif , dp - > tdir_tag , ( uint32 ) ( dp - > tdir_count ) , data ) ;
if ( data ! = 0 )
_TIFFfree ( data ) ;
if ( ! m )
return ( 0 ) ;
}
}
break ;
default :
assert ( 0 ) ; /* we should never get here */
break ;
}
if ( err ! = TIFFReadDirEntryErrOk )
{
TIFFReadDirEntryOutputErr ( tif , err , module , fip - > field_name , recover ) ;
return ( 0 ) ;
}
return ( 1 ) ;
2010-05-12 01:44:00 +08:00
}
/*
* Fetch a set of offsets or lengths .
* While this routine says " strips " , in fact it ' s also used for tiles .
*/
static int
2012-02-29 23:01:28 +08:00
TIFFFetchStripThing ( TIFF * tif , TIFFDirEntry * dir , uint32 nstrips , uint64 * * lpp )
2010-05-12 01:44:00 +08:00
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFFetchStripThing " ;
enum TIFFReadDirEntryErr err ;
uint64 * data ;
err = TIFFReadDirEntryLong8ArrayWithLimit ( tif , dir , & data , nstrips ) ;
if ( err ! = TIFFReadDirEntryErrOk )
{
const TIFFField * fip = TIFFFieldWithTag ( tif , dir - > tdir_tag ) ;
TIFFReadDirEntryOutputErr ( tif , err , module , fip ? fip - > field_name : " unknown tagname " , 0 ) ;
return ( 0 ) ;
}
if ( dir - > tdir_count < ( uint64 ) nstrips )
{
uint64 * resizeddata ;
const TIFFField * fip = TIFFFieldWithTag ( tif , dir - > tdir_tag ) ;
const char * pszMax = getenv ( " LIBTIFF_STRILE_ARRAY_MAX_RESIZE_COUNT " ) ;
uint32 max_nstrips = 1000000 ;
if ( pszMax )
max_nstrips = ( uint32 ) atoi ( pszMax ) ;
TIFFReadDirEntryOutputErr ( tif , TIFFReadDirEntryErrCount ,
module ,
fip ? fip - > field_name : " unknown tagname " ,
( nstrips < = max_nstrips ) ) ;
if ( nstrips > max_nstrips )
{
_TIFFfree ( data ) ;
return ( 0 ) ;
}
resizeddata = ( uint64 * ) _TIFFCheckMalloc ( tif , nstrips , sizeof ( uint64 ) , " for strip array " ) ;
if ( resizeddata = = 0 ) {
_TIFFfree ( data ) ;
return ( 0 ) ;
}
_TIFFmemcpy ( resizeddata , data , ( uint32 ) dir - > tdir_count * sizeof ( uint64 ) ) ;
_TIFFmemset ( resizeddata + ( uint32 ) dir - > tdir_count , 0 , ( nstrips - ( uint32 ) dir - > tdir_count ) * sizeof ( uint64 ) ) ;
_TIFFfree ( data ) ;
data = resizeddata ;
}
* lpp = data ;
return ( 1 ) ;
2010-05-12 01:44:00 +08:00
}
/*
2010-07-16 20:54:53 +08:00
* Fetch and set the SubjectDistance EXIF tag .
*/
static int
TIFFFetchSubjectDistance ( TIFF * tif , TIFFDirEntry * dir )
{
2017-12-08 20:47:54 +08:00
static const char module [ ] = " TIFFFetchSubjectDistance " ;
enum TIFFReadDirEntryErr err ;
UInt64Aligned_t m ;
2012-02-29 23:01:28 +08:00
m . l = 0 ;
2017-12-08 20:47:54 +08:00
assert ( sizeof ( double ) = = 8 ) ;
assert ( sizeof ( uint64 ) = = 8 ) ;
assert ( sizeof ( uint32 ) = = 4 ) ;
if ( dir - > tdir_count ! = 1 )
err = TIFFReadDirEntryErrCount ;
else if ( dir - > tdir_type ! = TIFF_RATIONAL )
err = TIFFReadDirEntryErrType ;
else
{
if ( ! ( tif - > tif_flags & TIFF_BIGTIFF ) )
{
uint32 offset ;
offset = * ( uint32 * ) ( & dir - > tdir_offset ) ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabLong ( & offset ) ;
err = TIFFReadDirEntryData ( tif , offset , 8 , m . i ) ;
}
else
{
m . l = dir - > tdir_offset . toff_long8 ;
err = TIFFReadDirEntryErrOk ;
}
}
if ( err = = TIFFReadDirEntryErrOk )
{
double n ;
if ( tif - > tif_flags & TIFF_SWAB )
TIFFSwabArrayOfLong ( m . i , 2 ) ;
if ( m . i [ 0 ] = = 0 )
n = 0.0 ;
2021-03-02 07:17:30 +08:00
else if ( m . i [ 0 ] = = 0xFFFFFFFF | | m . i [ 1 ] = = 0 )
2017-12-08 20:47:54 +08:00
/*
* XXX : Numerator 0xFFFFFFFF means that we have infinite
* distance . Indicate that with a negative floating point
* SubjectDistance value .
*/
n = - 1.0 ;
else
n = ( double ) m . i [ 0 ] / ( double ) m . i [ 1 ] ;
return ( TIFFSetField ( tif , dir - > tdir_tag , n ) ) ;
}
else
{
TIFFReadDirEntryOutputErr ( tif , err , module , " SubjectDistance " , TRUE ) ;
return ( 0 ) ;
}
2010-07-16 20:54:53 +08:00
}
2020-03-24 02:43:45 +08:00
static void allocChoppedUpStripArrays ( TIFF * tif , uint32 nstrips ,
uint64 stripbytes , uint32 rowsperstrip )
{
TIFFDirectory * td = & tif - > tif_dir ;
uint64 bytecount ;
uint64 offset ;
2021-03-02 07:17:30 +08:00
uint64 last_offset ;
uint64 last_bytecount ;
2020-03-24 02:43:45 +08:00
uint32 i ;
uint64 * newcounts ;
uint64 * newoffsets ;
2021-03-02 07:17:30 +08:00
offset = TIFFGetStrileOffset ( tif , 0 ) ;
last_offset = TIFFGetStrileOffset ( tif , td - > td_nstrips - 1 ) ;
last_bytecount = TIFFGetStrileByteCount ( tif , td - > td_nstrips - 1 ) ;
if ( last_offset > TIFF_UINT64_MAX - last_bytecount | |
last_offset + last_bytecount < offset )
{
return ;
}
bytecount = last_offset + last_bytecount - offset ;
2020-03-24 02:43:45 +08:00
newcounts = ( uint64 * ) _TIFFCheckMalloc ( tif , nstrips , sizeof ( uint64 ) ,
" for chopped \" StripByteCounts \" array " ) ;
newoffsets = ( uint64 * ) _TIFFCheckMalloc ( tif , nstrips , sizeof ( uint64 ) ,
" for chopped \" StripOffsets \" array " ) ;
if ( newcounts = = NULL | | newoffsets = = NULL ) {
/*
* Unable to allocate new strip information , give up and use
* the original one strip information .
*/
if ( newcounts ! = NULL )
_TIFFfree ( newcounts ) ;
if ( newoffsets ! = NULL )
_TIFFfree ( newoffsets ) ;
return ;
}
/*
* Fill the strip information arrays with new bytecounts and offsets
* that reflect the broken - up format .
*/
for ( i = 0 ; i < nstrips ; i + + )
{
if ( stripbytes > bytecount )
stripbytes = bytecount ;
newcounts [ i ] = stripbytes ;
newoffsets [ i ] = stripbytes ? offset : 0 ;
offset + = stripbytes ;
bytecount - = stripbytes ;
}
/*
* Replace old single strip info with multi - strip info .
*/
td - > td_stripsperimage = td - > td_nstrips = nstrips ;
TIFFSetField ( tif , TIFFTAG_ROWSPERSTRIP , rowsperstrip ) ;
2021-03-02 07:17:30 +08:00
_TIFFfree ( td - > td_stripbytecount_p ) ;
_TIFFfree ( td - > td_stripoffset_p ) ;
td - > td_stripbytecount_p = newcounts ;
td - > td_stripoffset_p = newoffsets ;
# ifdef STRIPBYTECOUNTSORTED_UNUSED
2020-03-24 02:43:45 +08:00
td - > td_stripbytecountsorted = 1 ;
2021-03-02 07:17:30 +08:00
# endif
tif - > tif_flags | = TIFF_CHOPPEDUPARRAYS ;
2020-03-24 02:43:45 +08:00
}
2010-07-16 20:54:53 +08:00
/*
* Replace a single strip ( tile ) of uncompressed data by multiple strips
* ( tiles ) , each approximately STRIP_SIZE_DEFAULT bytes . This is useful for
* dealing with large images or for dealing with machines with a limited
* amount memory .
2010-05-12 01:44:00 +08:00
*/
static void
ChopUpSingleUncompressedStrip ( TIFF * tif )
{
2017-12-08 20:47:54 +08:00
register TIFFDirectory * td = & tif - > tif_dir ;
uint64 bytecount ;
uint64 offset ;
uint32 rowblock ;
uint64 rowblockbytes ;
uint64 stripbytes ;
uint32 nstrips ;
uint32 rowsperstrip ;
2021-03-02 07:17:30 +08:00
bytecount = TIFFGetStrileByteCount ( tif , 0 ) ;
2017-12-08 20:47:54 +08:00
/* On a newly created file, just re-opened to be filled, we */
/* don't want strip chop to trigger as it is going to cause issues */
/* later ( StripOffsets and StripByteCounts improperly filled) . */
if ( bytecount = = 0 & & tif - > tif_mode ! = O_RDONLY )
return ;
2021-03-02 07:17:30 +08:00
offset = TIFFGetStrileByteCount ( tif , 0 ) ;
2017-12-08 20:47:54 +08:00
assert ( td - > td_planarconfig = = PLANARCONFIG_CONTIG ) ;
if ( ( td - > td_photometric = = PHOTOMETRIC_YCBCR ) & &
( ! isUpSampled ( tif ) ) )
rowblock = td - > td_ycbcrsubsampling [ 1 ] ;
else
rowblock = 1 ;
rowblockbytes = TIFFVTileSize64 ( tif , rowblock ) ;
/*
* Make the rows hold at least one scanline , but fill specified amount
* of data if possible .
*/
if ( rowblockbytes > STRIP_SIZE_DEFAULT ) {
stripbytes = rowblockbytes ;
rowsperstrip = rowblock ;
} else if ( rowblockbytes > 0 ) {
uint32 rowblocksperstrip ;
rowblocksperstrip = ( uint32 ) ( STRIP_SIZE_DEFAULT / rowblockbytes ) ;
rowsperstrip = rowblocksperstrip * rowblock ;
stripbytes = rowblocksperstrip * rowblockbytes ;
}
else
return ;
/*
* never increase the number of rows per strip
*/
if ( rowsperstrip > = td - > td_rowsperstrip )
return ;
nstrips = TIFFhowmany_32 ( td - > td_imagelength , rowsperstrip ) ;
if ( nstrips = = 0 )
return ;
2019-02-12 21:43:58 +08:00
/* If we are going to allocate a lot of memory, make sure that the */
/* file is as big as needed */
if ( tif - > tif_mode = = O_RDONLY & &
nstrips > 1000000 & &
( offset > = TIFFGetFileSize ( tif ) | |
stripbytes > ( TIFFGetFileSize ( tif ) - offset ) / ( nstrips - 1 ) ) )
{
return ;
}
2020-03-24 02:43:45 +08:00
allocChoppedUpStripArrays ( tif , nstrips , stripbytes , rowsperstrip ) ;
2010-05-12 01:44:00 +08:00
}
2020-03-24 02:43:45 +08:00
/*
* Replace a file with contiguous strips > 2 GB of uncompressed data by
* multiple smaller strips . This is useful for
* dealing with large images or for dealing with machines with a limited
* amount memory .
*/
static void TryChopUpUncompressedBigTiff ( TIFF * tif )
{
TIFFDirectory * td = & tif - > tif_dir ;
uint32 rowblock ;
uint64 rowblockbytes ;
uint32 i ;
uint64 stripsize ;
uint32 rowblocksperstrip ;
uint32 rowsperstrip ;
uint64 stripbytes ;
uint32 nstrips ;
stripsize = TIFFStripSize64 ( tif ) ;
assert ( tif - > tif_dir . td_planarconfig = = PLANARCONFIG_CONTIG ) ;
assert ( tif - > tif_dir . td_compression = = COMPRESSION_NONE ) ;
assert ( ( tif - > tif_flags & ( TIFF_STRIPCHOP | TIFF_ISTILED ) ) = = TIFF_STRIPCHOP ) ;
assert ( stripsize > 0x7FFFFFFFUL ) ;
/* On a newly created file, just re-opened to be filled, we */
/* don't want strip chop to trigger as it is going to cause issues */
/* later ( StripOffsets and StripByteCounts improperly filled) . */
2021-03-02 07:17:30 +08:00
if ( TIFFGetStrileByteCount ( tif , 0 ) = = 0 & & tif - > tif_mode ! = O_RDONLY )
2020-03-24 02:43:45 +08:00
return ;
if ( ( td - > td_photometric = = PHOTOMETRIC_YCBCR ) & &
( ! isUpSampled ( tif ) ) )
rowblock = td - > td_ycbcrsubsampling [ 1 ] ;
else
rowblock = 1 ;
rowblockbytes = TIFFVStripSize64 ( tif , rowblock ) ;
if ( rowblockbytes = = 0 | | rowblockbytes > 0x7FFFFFFFUL )
{
/* In case of file with gigantic width */
return ;
}
/* Check that the strips are contiguous and of the expected size */
for ( i = 0 ; i < td - > td_nstrips ; i + + )
{
if ( i = = td - > td_nstrips - 1 )
{
2021-03-02 07:17:30 +08:00
if ( TIFFGetStrileByteCount ( tif , i ) < TIFFVStripSize64 (
2020-03-24 02:43:45 +08:00
tif , td - > td_imagelength - i * td - > td_rowsperstrip ) )
{
return ;
}
}
else
{
2021-03-02 07:17:30 +08:00
if ( TIFFGetStrileByteCount ( tif , i ) ! = stripsize )
2020-03-24 02:43:45 +08:00
{
return ;
}
2021-03-02 07:17:30 +08:00
if ( i > 0 & & TIFFGetStrileOffset ( tif , i ) ! =
TIFFGetStrileOffset ( tif , i - 1 ) + TIFFGetStrileByteCount ( tif , i - 1 ) )
2020-03-24 02:43:45 +08:00
{
return ;
}
}
}
/* Aim for 512 MB strips (that will still be manageable by 32 bit builds */
rowblocksperstrip = ( uint32 ) ( 512 * 1024 * 1024 / rowblockbytes ) ;
if ( rowblocksperstrip = = 0 )
rowblocksperstrip = 1 ;
rowsperstrip = rowblocksperstrip * rowblock ;
stripbytes = rowblocksperstrip * rowblockbytes ;
assert ( stripbytes < = 0x7FFFFFFFUL ) ;
nstrips = TIFFhowmany_32 ( td - > td_imagelength , rowsperstrip ) ;
if ( nstrips = = 0 )
return ;
/* If we are going to allocate a lot of memory, make sure that the */
/* file is as big as needed */
if ( tif - > tif_mode = = O_RDONLY & &
2021-03-02 07:17:30 +08:00
nstrips > 1000000 )
2020-03-24 02:43:45 +08:00
{
2021-03-02 07:17:30 +08:00
uint64 last_offset = TIFFGetStrileOffset ( tif , td - > td_nstrips - 1 ) ;
uint64 filesize = TIFFGetFileSize ( tif ) ;
uint64 last_bytecount = TIFFGetStrileByteCount ( tif , td - > td_nstrips - 1 ) ;
if ( last_offset > filesize | |
last_bytecount > filesize - last_offset )
{
return ;
}
2020-03-24 02:43:45 +08:00
}
allocChoppedUpStripArrays ( tif , nstrips , stripbytes , rowsperstrip ) ;
}
2021-03-02 07:17:30 +08:00
TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
static uint64 _TIFFUnsanitizedAddUInt64AndInt ( uint64 a , int b )
2017-12-08 20:47:54 +08:00
{
2021-03-02 07:17:30 +08:00
return a + b ;
2017-12-08 20:47:54 +08:00
}
2021-03-02 07:17:30 +08:00
/* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around
* strip / tile of number strile . Also fetch the neighbouring values using a
* 4096 byte page size .
*/
static
int _TIFFPartialReadStripArray ( TIFF * tif , TIFFDirEntry * dirent ,
int strile , uint64 * panVals )
2012-02-29 23:01:28 +08:00
{
2021-03-02 07:17:30 +08:00
static const char module [ ] = " _TIFFPartialReadStripArray " ;
# define IO_CACHE_PAGE_SIZE 4096
size_t sizeofval ;
const int bSwab = ( tif - > tif_flags & TIFF_SWAB ) ! = 0 ;
int sizeofvalint ;
uint64 nBaseOffset ;
uint64 nOffset ;
uint64 nOffsetStartPage ;
uint64 nOffsetEndPage ;
tmsize_t nToRead ;
tmsize_t nRead ;
uint64 nLastStripOffset ;
int iStartBefore ;
int i ;
const uint32 arraySize = tif - > tif_dir . td_stripoffsetbyteallocsize ;
unsigned char buffer [ 2 * IO_CACHE_PAGE_SIZE ] ;
assert ( dirent - > tdir_count > 4 ) ;
if ( dirent - > tdir_type = = TIFF_SHORT )
{
sizeofval = sizeof ( uint16 ) ;
}
else if ( dirent - > tdir_type = = TIFF_LONG )
{
sizeofval = sizeof ( uint32 ) ;
}
else if ( dirent - > tdir_type = = TIFF_LONG8 )
{
sizeofval = sizeof ( uint64 ) ;
}
else if ( dirent - > tdir_type = = TIFF_SLONG8 )
{
/* Non conformant but used by some images as in */
/* https://github.com/OSGeo/gdal/issues/2165 */
sizeofval = sizeof ( int64 ) ;
}
else
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Invalid type for [Strip|Tile][Offset/ByteCount] tag " ) ;
panVals [ strile ] = 0 ;
return 0 ;
}
sizeofvalint = ( int ) ( sizeofval ) ;
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
if ( tif - > tif_flags & TIFF_BIGTIFF )
{
uint64 offset = dirent - > tdir_offset . toff_long8 ;
if ( bSwab )
TIFFSwabLong8 ( & offset ) ;
nBaseOffset = offset ;
}
else
{
uint32 offset = dirent - > tdir_offset . toff_long ;
if ( bSwab )
TIFFSwabLong ( & offset ) ;
nBaseOffset = offset ;
}
/* To avoid later unsigned integer overflows */
if ( nBaseOffset > ( uint64 ) TIFF_INT64_MAX )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot read offset/size for strile %d " , strile ) ;
panVals [ strile ] = 0 ;
return 0 ;
}
nOffset = nBaseOffset + sizeofval * strile ;
nOffsetStartPage =
( nOffset / IO_CACHE_PAGE_SIZE ) * IO_CACHE_PAGE_SIZE ;
nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE ;
if ( nOffset + sizeofval > nOffsetEndPage )
nOffsetEndPage + = IO_CACHE_PAGE_SIZE ;
# undef IO_CACHE_PAGE_SIZE
nLastStripOffset = nBaseOffset + arraySize * sizeofval ;
if ( nLastStripOffset < nOffsetEndPage )
nOffsetEndPage = nLastStripOffset ;
if ( nOffsetStartPage > = nOffsetEndPage )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot read offset/size for strile %d " , strile ) ;
panVals [ strile ] = 0 ;
return 0 ;
}
if ( ! SeekOK ( tif , nOffsetStartPage ) )
{
panVals [ strile ] = 0 ;
return 0 ;
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
nToRead = ( tmsize_t ) ( nOffsetEndPage - nOffsetStartPage ) ;
nRead = TIFFReadFile ( tif , buffer , nToRead ) ;
if ( nRead < nToRead )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot read offset/size for strile around ~%d " , strile ) ;
return 0 ;
}
iStartBefore = - ( int ) ( ( nOffset - nOffsetStartPage ) / sizeofval ) ;
if ( strile + iStartBefore < 0 )
iStartBefore = - strile ;
for ( i = iStartBefore ;
( uint32 ) ( strile + i ) < arraySize & &
_TIFFUnsanitizedAddUInt64AndInt ( nOffset , ( i + 1 ) * sizeofvalint ) < = nOffsetEndPage ;
+ + i )
{
if ( dirent - > tdir_type = = TIFF_SHORT )
{
uint16 val ;
memcpy ( & val ,
buffer + ( nOffset - nOffsetStartPage ) + i * sizeofvalint ,
sizeof ( val ) ) ;
if ( bSwab )
TIFFSwabShort ( & val ) ;
panVals [ strile + i ] = val ;
}
else if ( dirent - > tdir_type = = TIFF_LONG )
{
uint32 val ;
memcpy ( & val ,
buffer + ( nOffset - nOffsetStartPage ) + i * sizeofvalint ,
sizeof ( val ) ) ;
if ( bSwab )
TIFFSwabLong ( & val ) ;
panVals [ strile + i ] = val ;
}
else if ( dirent - > tdir_type = = TIFF_LONG8 )
{
uint64 val ;
memcpy ( & val ,
buffer + ( nOffset - nOffsetStartPage ) + i * sizeofvalint ,
sizeof ( val ) ) ;
if ( bSwab )
TIFFSwabLong8 ( & val ) ;
panVals [ strile + i ] = val ;
}
else /* if( dirent->tdir_type == TIFF_SLONG8 ) */
{
/* Non conformant data type */
int64 val ;
memcpy ( & val ,
buffer + ( nOffset - nOffsetStartPage ) + i * sizeofvalint ,
sizeof ( val ) ) ;
if ( bSwab )
TIFFSwabLong8 ( ( uint64 * ) & val ) ;
panVals [ strile + i ] = ( uint64 ) val ;
}
}
return 1 ;
}
static int _TIFFFetchStrileValue ( TIFF * tif ,
uint32 strile ,
TIFFDirEntry * dirent ,
uint64 * * parray )
{
static const char module [ ] = " _TIFFFetchStrileValue " ;
TIFFDirectory * td = & tif - > tif_dir ;
if ( strile > = dirent - > tdir_count )
{
return 0 ;
}
if ( strile > = td - > td_stripoffsetbyteallocsize )
{
uint32 nStripArrayAllocBefore = td - > td_stripoffsetbyteallocsize ;
uint32 nStripArrayAllocNew ;
uint64 nArraySize64 ;
size_t nArraySize ;
uint64 * offsetArray ;
uint64 * bytecountArray ;
if ( strile > 1000000 )
{
uint64 filesize = TIFFGetFileSize ( tif ) ;
/* Avoid excessive memory allocation attempt */
/* For such a big blockid we need at least a TIFF_LONG per strile */
/* for the offset array. */
if ( strile > filesize / sizeof ( uint32 ) )
{
TIFFErrorExt ( tif - > tif_clientdata , module , " File too short " ) ;
2012-02-29 23:01:28 +08:00
return 0 ;
2021-03-02 07:17:30 +08:00
}
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
if ( td - > td_stripoffsetbyteallocsize = = 0 & &
td - > td_nstrips < 1024 * 1024 )
2012-02-29 23:01:28 +08:00
{
2021-03-02 07:17:30 +08:00
nStripArrayAllocNew = td - > td_nstrips ;
2012-02-29 23:01:28 +08:00
}
2021-03-02 07:17:30 +08:00
else
{
# define TIFF_MAX(a,b) (((a)>(b)) ? (a) : (b))
# define TIFF_MIN(a,b) (((a)<(b)) ? (a) : (b))
nStripArrayAllocNew = TIFF_MAX ( strile + 1 , 1024U * 512U ) ;
if ( nStripArrayAllocNew < 0xFFFFFFFFU / 2 )
nStripArrayAllocNew * = 2 ;
nStripArrayAllocNew = TIFF_MIN ( nStripArrayAllocNew , td - > td_nstrips ) ;
}
assert ( strile < nStripArrayAllocNew ) ;
nArraySize64 = ( uint64 ) sizeof ( uint64 ) * nStripArrayAllocNew ;
nArraySize = ( size_t ) ( nArraySize64 ) ;
# if SIZEOF_SIZE_T == 4
if ( nArraySize ! = nArraySize64 )
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot allocate strip offset and bytecount arrays " ) ;
return 0 ;
}
# endif
offsetArray = ( uint64 * ) (
_TIFFrealloc ( td - > td_stripoffset_p , nArraySize ) ) ;
bytecountArray = ( uint64 * ) (
_TIFFrealloc ( td - > td_stripbytecount_p , nArraySize ) ) ;
if ( offsetArray )
td - > td_stripoffset_p = offsetArray ;
if ( bytecountArray )
td - > td_stripbytecount_p = bytecountArray ;
if ( offsetArray & & bytecountArray )
{
td - > td_stripoffsetbyteallocsize = nStripArrayAllocNew ;
/* Initialize new entries to ~0 / -1 */
memset ( td - > td_stripoffset_p + nStripArrayAllocBefore ,
0xFF ,
( td - > td_stripoffsetbyteallocsize - nStripArrayAllocBefore ) * sizeof ( uint64 ) ) ;
memset ( td - > td_stripbytecount_p + nStripArrayAllocBefore ,
0xFF ,
( td - > td_stripoffsetbyteallocsize - nStripArrayAllocBefore ) * sizeof ( uint64 ) ) ;
}
else
{
TIFFErrorExt ( tif - > tif_clientdata , module ,
" Cannot allocate strip offset and bytecount arrays " ) ;
_TIFFfree ( td - > td_stripoffset_p ) ;
td - > td_stripoffset_p = NULL ;
_TIFFfree ( td - > td_stripbytecount_p ) ;
td - > td_stripbytecount_p = NULL ;
td - > td_stripoffsetbyteallocsize = 0 ;
}
}
if ( * parray = = NULL | | strile > = td - > td_stripoffsetbyteallocsize )
return 0 ;
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
if ( ~ ( ( * parray ) [ strile ] ) = = 0 )
{
if ( ! _TIFFPartialReadStripArray ( tif , dirent , strile , * parray ) )
2012-02-29 23:01:28 +08:00
{
2021-03-02 07:17:30 +08:00
( * parray ) [ strile ] = 0 ;
return 0 ;
2012-02-29 23:01:28 +08:00
}
2021-03-02 07:17:30 +08:00
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
return 1 ;
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
static uint64 _TIFFGetStrileOffsetOrByteCountValue ( TIFF * tif , uint32 strile ,
TIFFDirEntry * dirent ,
uint64 * * parray ,
int * pbErr )
{
TIFFDirectory * td = & tif - > tif_dir ;
if ( pbErr )
* pbErr = 0 ;
if ( ( tif - > tif_flags & TIFF_DEFERSTRILELOAD ) & & ! ( tif - > tif_flags & TIFF_CHOPPEDUPARRAYS ) )
{
if ( ! ( tif - > tif_flags & TIFF_LAZYSTRILELOAD ) | |
/* If the values may fit in the toff_long/toff_long8 member */
/* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */
dirent - > tdir_count < = 4 )
{
if ( ! _TIFFFillStriles ( tif ) )
{
if ( pbErr )
* pbErr = 1 ;
/* Do not return, as we want this function to always */
/* return the same value if called several times with */
/* the same arguments */
}
}
else
{
if ( ! _TIFFFetchStrileValue ( tif , strile , dirent , parray ) )
{
if ( pbErr )
* pbErr = 1 ;
return 0 ;
}
}
}
if ( * parray = = NULL | | strile > = td - > td_nstrips )
{
if ( pbErr )
* pbErr = 1 ;
return 0 ;
}
return ( * parray ) [ strile ] ;
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */
uint64 TIFFGetStrileOffset ( TIFF * tif , uint32 strile )
{
return TIFFGetStrileOffsetWithErr ( tif , strile , NULL ) ;
}
2012-02-29 23:01:28 +08:00
2021-03-02 07:17:30 +08:00
/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */
uint64 TIFFGetStrileOffsetWithErr ( TIFF * tif , uint32 strile , int * pbErr )
{
TIFFDirectory * td = & tif - > tif_dir ;
return _TIFFGetStrileOffsetOrByteCountValue ( tif , strile ,
& ( td - > td_stripoffset_entry ) ,
& ( td - > td_stripoffset_p ) , pbErr ) ;
}
/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */
uint64 TIFFGetStrileByteCount ( TIFF * tif , uint32 strile )
{
return TIFFGetStrileByteCountWithErr ( tif , strile , NULL ) ;
}
/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */
uint64 TIFFGetStrileByteCountWithErr ( TIFF * tif , uint32 strile , int * pbErr )
{
TIFFDirectory * td = & tif - > tif_dir ;
return _TIFFGetStrileOffsetOrByteCountValue ( tif , strile ,
& ( td - > td_stripbytecount_entry ) ,
& ( td - > td_stripbytecount_p ) , pbErr ) ;
}
int _TIFFFillStriles ( TIFF * tif )
{
return _TIFFFillStrilesInternal ( tif , 1 ) ;
}
static int _TIFFFillStrilesInternal ( TIFF * tif , int loadStripByteCount )
{
register TIFFDirectory * td = & tif - > tif_dir ;
int return_value = 1 ;
/* Do not do anything if TIFF_DEFERSTRILELOAD is not set */
if ( ! ( tif - > tif_flags & TIFF_DEFERSTRILELOAD ) | | ( tif - > tif_flags & TIFF_CHOPPEDUPARRAYS ) ! = 0 )
2012-02-29 23:01:28 +08:00
return 1 ;
2021-03-02 07:17:30 +08:00
if ( tif - > tif_flags & TIFF_LAZYSTRILELOAD )
{
/* In case of lazy loading, reload completely the arrays */
_TIFFfree ( td - > td_stripoffset_p ) ;
_TIFFfree ( td - > td_stripbytecount_p ) ;
td - > td_stripoffset_p = NULL ;
td - > td_stripbytecount_p = NULL ;
td - > td_stripoffsetbyteallocsize = 0 ;
tif - > tif_flags & = ~ TIFF_LAZYSTRILELOAD ;
}
/* If stripoffset array is already loaded, exit with success */
if ( td - > td_stripoffset_p ! = NULL )
return 1 ;
/* If tdir_count was canceled, then we already got there, but in error */
if ( td - > td_stripoffset_entry . tdir_count = = 0 )
return 0 ;
if ( ! TIFFFetchStripThing ( tif , & ( td - > td_stripoffset_entry ) ,
td - > td_nstrips , & td - > td_stripoffset_p ) )
{
return_value = 0 ;
}
if ( loadStripByteCount & &
! TIFFFetchStripThing ( tif , & ( td - > td_stripbytecount_entry ) ,
td - > td_nstrips , & td - > td_stripbytecount_p ) )
{
return_value = 0 ;
}
_TIFFmemset ( & ( td - > td_stripoffset_entry ) , 0 , sizeof ( TIFFDirEntry ) ) ;
_TIFFmemset ( & ( td - > td_stripbytecount_entry ) , 0 , sizeof ( TIFFDirEntry ) ) ;
# ifdef STRIPBYTECOUNTSORTED_UNUSED
if ( tif - > tif_dir . td_nstrips > 1 & & return_value = = 1 ) {
uint32 strip ;
tif - > tif_dir . td_stripbytecountsorted = 1 ;
for ( strip = 1 ; strip < tif - > tif_dir . td_nstrips ; strip + + ) {
if ( tif - > tif_dir . td_stripoffset_p [ strip - 1 ] >
tif - > tif_dir . td_stripoffset_p [ strip ] ) {
tif - > tif_dir . td_stripbytecountsorted = 0 ;
break ;
}
}
}
# endif
return return_value ;
2012-02-29 23:01:28 +08:00
}
2010-05-12 01:44:00 +08:00
/* vim: set ts=8 sts=8 sw=8 noet: */
2010-07-16 20:54:53 +08:00
/*
* Local Variables :
* mode : c
* c - basic - offset : 8
* fill - column : 78
* End :
*/