blob: 4a5015ea2266c506c0b244f3f96ae7b1764c190e [file] [log] [blame]
/*
* Copyright (c) 1988-1997 Sam Leffler
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
*
* Permission to use, copy, modify, distribute, and sell this software and
* 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.
*
* 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.
*
* 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,
* 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
* OF THIS SOFTWARE.
*/
/*
* TIFF Library.
*
* Directory Read Support Routines.
*/
/* 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.
*/
#include "tiffconf.h"
#include "tiffiop.h"
#include <float.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#define FAILED_FII ((uint32_t)-1)
#ifdef HAVE_IEEEFP
#define TIFFCvtIEEEFloatToNative(tif, n, fp)
#define TIFFCvtIEEEDoubleToNative(tif, n, dp)
#else
extern void TIFFCvtIEEEFloatToNative(TIFF *, uint32_t, float *);
extern void TIFFCvtIEEEDoubleToNative(TIFF *, uint32_t, double *);
#endif
enum TIFFReadDirEntryErr
{
TIFFReadDirEntryErrOk = 0,
TIFFReadDirEntryErrCount = 1,
TIFFReadDirEntryErrType = 2,
TIFFReadDirEntryErrIo = 3,
TIFFReadDirEntryErrRange = 4,
TIFFReadDirEntryErrPsdif = 5,
TIFFReadDirEntryErrSizesan = 6,
TIFFReadDirEntryErrAlloc = 7,
};
static enum TIFFReadDirEntryErr
TIFFReadDirEntryByte(TIFF *tif, TIFFDirEntry *direntry, uint8_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySbyte(TIFF *tif, TIFFDirEntry *direntry, int8_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryShort(TIFF *tif, TIFFDirEntry *direntry, uint16_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong(TIFF *tif, TIFFDirEntry *direntry, int32_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *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_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t *count,
uint32_t desttypesize, void **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **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_t **value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryPersampleShort(TIFF *tif, TIFFDirEntry *direntry,
uint16_t *value);
static void TIFFReadDirEntryCheckedByte(TIFF *tif, TIFFDirEntry *direntry,
uint8_t *value);
static void TIFFReadDirEntryCheckedSbyte(TIFF *tif, TIFFDirEntry *direntry,
int8_t *value);
static void TIFFReadDirEntryCheckedShort(TIFF *tif, TIFFDirEntry *direntry,
uint16_t *value);
static void TIFFReadDirEntryCheckedSshort(TIFF *tif, TIFFDirEntry *direntry,
int16_t *value);
static void TIFFReadDirEntryCheckedLong(TIFF *tif, TIFFDirEntry *direntry,
uint32_t *value);
static void TIFFReadDirEntryCheckedSlong(TIFF *tif, TIFFDirEntry *direntry,
int32_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckedLong8(TIFF *tif, TIFFDirEntry *direntry,
uint64_t *value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckedSlong8(TIFF *tif, TIFFDirEntry *direntry,
int64_t *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);
#if 0
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckedRationalDirect(TIFF *tif, TIFFDirEntry *direntry,
TIFFRational_t *value);
#endif
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteSbyte(int8_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteShort(uint16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteSshort(int16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteLong(uint32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteSlong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeByteSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteByte(uint8_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteShort(uint16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteSshort(int16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteLong(uint32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteSlong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSbyteSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortSbyte(int8_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortSshort(int16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortLong(uint32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortSlong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeShortSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSshortShort(uint16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSshortLong(uint32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSshortSlong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSshortLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSshortSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongSbyte(int8_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongSshort(int16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongSlong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLongSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongLong(uint32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongLong8(uint64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlongSlong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Sbyte(int8_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Sshort(int16_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Slong(int32_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeLong8Slong8(int64_t value);
static enum TIFFReadDirEntryErr
TIFFReadDirEntryCheckRangeSlong8Long8(uint64_t value);
static enum TIFFReadDirEntryErr TIFFReadDirEntryData(TIFF *tif, uint64_t 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_t dircount);
static TIFFDirEntry *TIFFReadDirectoryFindEntry(TIFF *tif, TIFFDirEntry *dir,
uint16_t dircount,
uint16_t tagid);
static void TIFFReadDirectoryFindFieldInfo(TIFF *tif, uint16_t tagid,
uint32_t *fii);
static int EstimateStripByteCounts(TIFF *tif, TIFFDirEntry *dir,
uint16_t dircount);
static void MissingRequired(TIFF *, const char *);
static int CheckDirCount(TIFF *, TIFFDirEntry *, uint32_t);
static uint16_t TIFFFetchDirectory(TIFF *tif, uint64_t diroff,
TIFFDirEntry **pdir, uint64_t *nextdiroff);
static int TIFFFetchNormalTag(TIFF *, TIFFDirEntry *, int recover);
static int TIFFFetchStripThing(TIFF *tif, TIFFDirEntry *dir, uint32_t nstrips,
uint64_t **lpp);
static int TIFFFetchSubjectDistance(TIFF *, TIFFDirEntry *);
static void ChopUpSingleUncompressedStrip(TIFF *);
static void TryChopUpUncompressedBigTiff(TIFF *);
static uint64_t TIFFReadUInt64(const uint8_t *value);
static int _TIFFGetMaxColorChannels(uint16_t photometric);
static int _TIFFFillStrilesInternal(TIFF *tif, int loadStripByteCount);
typedef union _UInt64Aligned_t
{
double d;
uint64_t l;
uint32_t i[2];
uint16_t s[4];
uint8_t c[8];
} UInt64Aligned_t;
/*
Unaligned safe copy of a uint64_t value from an octet array.
*/
static uint64_t TIFFReadUInt64(const uint8_t *value)
{
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;
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryByte(TIFF *tif, TIFFDirEntry *direntry, uint8_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with
field_readcount==1 */
TIFFReadDirEntryCheckedByte(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeByteSbyte(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeByteShort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeByteSshort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeByteLong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeByteSlong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeByteLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeByteSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint8_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySbyte(TIFF *tif, TIFFDirEntry *direntry, int8_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
case TIFF_UNDEFINED: /* Support to read TIFF_UNDEFINED with
field_readcount==1 */
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSbyteByte(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
TIFFReadDirEntryCheckedSbyte(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSbyteShort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSbyteSshort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSbyteLong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSbyteSlong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSbyteLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSbyteSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int8_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntrySbyte() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntryShort(TIFF *tif, TIFFDirEntry *direntry, uint16_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeShortSbyte(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
TIFFReadDirEntryCheckedShort(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeShortSshort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeShortLong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeShortSlong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeShortLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeShortSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntryShort() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySshort(TIFF *tif, TIFFDirEntry *direntry, int16_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSshortShort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
TIFFReadDirEntryCheckedSshort(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSshortLong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSshortSlong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSshortLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSshortSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int16_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntrySshort() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong(TIFF *tif, TIFFDirEntry *direntry, uint32_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLongSbyte(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLongSshort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
TIFFReadDirEntryCheckedLong(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLongSlong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeLongLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeLongSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint32_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntryLong() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong(TIFF *tif, TIFFDirEntry *direntry, int32_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeSlongLong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
TIFFReadDirEntryCheckedSlong(tif, direntry, value);
return (TIFFReadDirEntryErrOk);
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSlongLong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSlongSlong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int32_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntrySlong() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLong8Sbyte(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLong8Sshort(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
err = TIFFReadDirEntryCheckRangeLong8Slong(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
return (err);
case TIFF_SLONG8:
{
int64_t m;
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeLong8Slong8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntryLong8() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong8(TIFF *tif, TIFFDirEntry *direntry, int64_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
err = TIFFReadDirEntryCheckRangeSlong8Long8(m);
if (err != TIFFReadDirEntryErrOk)
return (err);
*value = (int64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
err = TIFFReadDirEntryCheckedSlong8(tif, direntry, value);
return (err);
default:
return (TIFFReadDirEntryErrType);
}
} /*-- TIFFReadDirEntrySlong8() --*/
static enum TIFFReadDirEntryErr
TIFFReadDirEntryFloat(TIFF *tif, TIFFDirEntry *direntry, float *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
#if defined(__WIN32__) && (_MSC_VER < 1500)
/*
* XXX: MSVC 6.0 does not support conversion
* of 64-bit integers into floating point
* values.
*/
*value = _TIFFUInt64ToFloat(m);
#else
*value = (float)m;
#endif
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t 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);
if ((m > FLT_MAX) || (m < -FLT_MAX))
return (TIFFReadDirEntryErrRange);
*value = (float)m;
return (TIFFReadDirEntryErrOk);
}
default:
return (TIFFReadDirEntryErrType);
}
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryDouble(TIFF *tif, TIFFDirEntry *direntry, double *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t m;
TIFFReadDirEntryCheckedByte(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
{
int8_t m;
TIFFReadDirEntryCheckedSbyte(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SHORT:
{
uint16_t m;
TIFFReadDirEntryCheckedShort(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
{
int16_t m;
TIFFReadDirEntryCheckedSshort(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
{
int32_t m;
TIFFReadDirEntryCheckedSlong(tif, direntry, &m);
*value = (double)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
{
uint64_t m;
err = TIFFReadDirEntryCheckedLong8(tif, direntry, &m);
if (err != TIFFReadDirEntryErrOk)
return (err);
#if defined(__WIN32__) && (_MSC_VER < 1500)
/*
* XXX: MSVC 6.0 does not support conversion
* of 64-bit integers into floating point
* values.
*/
*value = _TIFFUInt64ToDouble(m);
#else
*value = (double)m;
#endif
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
{
int64_t 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);
}
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryIfd8(TIFF *tif, TIFFDirEntry *direntry, uint64_t *value)
{
enum TIFFReadDirEntryErr err;
if (direntry->tdir_count != 1)
return (TIFFReadDirEntryErrCount);
switch (direntry->tdir_type)
{
case TIFF_LONG:
case TIFF_IFD:
{
uint32_t m;
TIFFReadDirEntryCheckedLong(tif, direntry, &m);
*value = (uint64_t)m;
return (TIFFReadDirEntryErrOk);
}
case TIFF_LONG8:
case TIFF_IFD8:
err = TIFFReadDirEntryCheckedLong8(tif, direntry, value);
return (err);
default:
return (TIFFReadDirEntryErrType);
}
}
#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_t offset,
tmsize_t size,
void **pdest)
{
#if SIZEOF_SIZE_T == 8
tmsize_t threshold = INITIAL_THRESHOLD;
#endif
tmsize_t already_read = 0;
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)
{
void *new_dest;
tmsize_t bytes_read;
tmsize_t to_read = size - already_read;
#if SIZEOF_SIZE_T == 8
if (to_read >= threshold && threshold < MAX_THRESHOLD)
{
to_read = threshold;
threshold *= THRESHOLD_MULTIPLIER;
}
#endif
new_dest =
(uint8_t *)_TIFFreallocExt(tif, *pdest, already_read + to_read);
if (new_dest == NULL)
{
TIFFErrorExtR(tif, tif->tif_name,
"Failed to allocate memory for %s "
"(%" TIFF_SSIZE_FORMAT
" elements of %" TIFF_SSIZE_FORMAT " bytes each)",
"TIFFReadDirEntryArray", (tmsize_t)1,
already_read + to_read);
return TIFFReadDirEntryErrAlloc;
}
*pdest = new_dest;
bytes_read = TIFFReadFile(tif, (char *)*pdest + already_read, to_read);
already_read += bytes_read;
if (bytes_read != to_read)
{
return TIFFReadDirEntryErrIo;
}
}
return TIFFReadDirEntryErrOk;
}
/* Caution: if raising that value, make sure int32 / uint32 overflows can't
* occur elsewhere */
#define MAX_SIZE_TAG_DATA 2147483647U
static enum TIFFReadDirEntryErr
TIFFReadDirEntryArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
uint32_t *count, uint32_t desttypesize,
void **value, uint64_t maxcount)
{
int typesize;
uint32_t datasize;
void *data;
uint64_t target_count64;
int original_datasize_clamped;
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;
/* 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;
/*
* As a sanity check, make sure we have no more than a 2GB tag array
* in either the current data type or the dest data type. This also
* avoids problems with overflow of tmsize_t on 32bit systems.
*/
if ((uint64_t)(MAX_SIZE_TAG_DATA / typesize) < target_count64)
return (TIFFReadDirEntryErrSizesan);
if ((uint64_t)(MAX_SIZE_TAG_DATA / desttypesize) < target_count64)
return (TIFFReadDirEntryErrSizesan);
*count = (uint32_t)target_count64;
datasize = (*count) * typesize;
assert((tmsize_t)datasize > 0);
if (isMapped(tif) && datasize > (uint64_t)tif->tif_size)
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))
{
/* Only the condition on original_datasize_clamped. The second
* one is implied, but Coverity Scan cannot see it. */
if (original_datasize_clamped <= 4 && datasize <= 4)
_TIFFmemcpy(data, &direntry->tdir_offset, datasize);
else
{
enum TIFFReadDirEntryErr err;
uint32_t offset = direntry->tdir_offset.toff_long;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong(&offset);
if (isMapped(tif))
err = TIFFReadDirEntryData(tif, (uint64_t)offset,
(tmsize_t)datasize, data);
else
err = TIFFReadDirEntryDataAndRealloc(tif, (uint64_t)offset,
(tmsize_t)datasize, &data);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
}
}
else
{
/* See above comment for the Classic TIFF case */
if (original_datasize_clamped <= 8 && datasize <= 8)
_TIFFmemcpy(data, &direntry->tdir_offset, datasize);
else
{
enum TIFFReadDirEntryErr err;
uint64_t offset = direntry->tdir_offset.toff_long8;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(&offset);
if (isMapped(tif))
err = TIFFReadDirEntryData(tif, (uint64_t)offset,
(tmsize_t)datasize, data);
else
err = TIFFReadDirEntryDataAndRealloc(tif, (uint64_t)offset,
(tmsize_t)datasize, &data);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
}
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t *count,
uint32_t desttypesize, void **value)
{
return TIFFReadDirEntryArrayWithLimit(tif, direntry, count, desttypesize,
value, ~((uint64_t)0));
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryByteArray(TIFF *tif, TIFFDirEntry *direntry, uint8_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
uint8_t *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_t *)origdata;
return (TIFFReadDirEntryErrOk);
case TIFF_SBYTE:
{
int8_t *m;
uint32_t n;
m = (int8_t *)origdata;
for (n = 0; n < count; n++)
{
err = TIFFReadDirEntryCheckRangeByteSbyte(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (uint8_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
}
data = (uint8_t *)_TIFFmallocExt(tif, count);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_SHORT:
{
uint16_t *ma;
uint8_t *mb;
uint32_t n;
ma = (uint16_t *)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_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
uint8_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
err = TIFFReadDirEntryCheckRangeByteSshort(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint8_t)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
uint8_t *mb;
uint32_t n;
ma = (uint32_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
uint8_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
err = TIFFReadDirEntryCheckRangeByteSlong(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint8_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
uint8_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
uint8_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeByteSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint8_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySbyteArray(TIFF *tif, TIFFDirEntry *direntry, int8_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
int8_t *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_t *m;
uint32_t n;
m = (uint8_t *)origdata;
for (n = 0; n < count; n++)
{
err = TIFFReadDirEntryCheckRangeSbyteByte(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (int8_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SBYTE:
*value = (int8_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
data = (int8_t *)_TIFFmallocExt(tif, count);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_SHORT:
{
uint16_t *ma;
int8_t *mb;
uint32_t n;
ma = (uint16_t *)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_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
int8_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
err = TIFFReadDirEntryCheckRangeSbyteSshort(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int8_t)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
int8_t *mb;
uint32_t n;
ma = (uint32_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
int8_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
err = TIFFReadDirEntryCheckRangeSbyteSlong(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int8_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
int8_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
int8_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeSbyteSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int8_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryShortArray(TIFF *tif, TIFFDirEntry *direntry, uint16_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
uint16_t *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_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfShort(*value, count);
return (TIFFReadDirEntryErrOk);
case TIFF_SSHORT:
{
int16_t *m;
uint32_t n;
m = (int16_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)m);
err = TIFFReadDirEntryCheckRangeShortSshort(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (uint16_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
}
data = (uint16_t *)_TIFFmallocExt(tif, count * 2);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
uint16_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (uint16_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
uint16_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
err = TIFFReadDirEntryCheckRangeShortSbyte(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint16_t)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
uint16_t *mb;
uint32_t n;
ma = (uint32_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
uint16_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
err = TIFFReadDirEntryCheckRangeShortSlong(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint16_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
uint16_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
uint16_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeShortSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint16_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySshortArray(TIFF *tif, TIFFDirEntry *direntry, int16_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
int16_t *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_t *m;
uint32_t n;
m = (uint16_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(m);
err = TIFFReadDirEntryCheckRangeSshortShort(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (int16_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SSHORT:
*value = (int16_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfShort((uint16_t *)(*value), count);
return (TIFFReadDirEntryErrOk);
}
data = (int16_t *)_TIFFmallocExt(tif, count * 2);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
int16_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int16_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
int16_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int16_t)(*ma++);
}
break;
case TIFF_LONG:
{
uint32_t *ma;
int16_t *mb;
uint32_t n;
ma = (uint32_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
int16_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
err = TIFFReadDirEntryCheckRangeSshortSlong(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int16_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
int16_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
int16_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeSshortSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int16_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLongArray(TIFF *tif, TIFFDirEntry *direntry, uint32_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
uint32_t *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_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong(*value, count);
return (TIFFReadDirEntryErrOk);
case TIFF_SLONG:
{
int32_t *m;
uint32_t n;
m = (int32_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)m);
err = TIFFReadDirEntryCheckRangeLongSlong(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (uint32_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
}
data = (uint32_t *)_TIFFmallocExt(tif, count * 4);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
uint32_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (uint32_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
uint32_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
err = TIFFReadDirEntryCheckRangeLongSbyte(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint32_t)(*ma++);
}
}
break;
case TIFF_SHORT:
{
uint16_t *ma;
uint32_t *mb;
uint32_t n;
ma = (uint16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(ma);
*mb++ = (uint32_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
uint32_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
err = TIFFReadDirEntryCheckRangeLongSshort(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint32_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
uint32_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
uint32_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeLongSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint32_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlongArray(TIFF *tif, TIFFDirEntry *direntry, int32_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
int32_t *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_t *m;
uint32_t n;
m = (uint32_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)m);
err = TIFFReadDirEntryCheckRangeSlongLong(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (int32_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG:
*value = (int32_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong((uint32_t *)(*value), count);
return (TIFFReadDirEntryErrOk);
}
data = (int32_t *)_TIFFmallocExt(tif, count * 4);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
int32_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int32_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
int32_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int32_t)(*ma++);
}
break;
case TIFF_SHORT:
{
uint16_t *ma;
int32_t *mb;
uint32_t n;
ma = (uint16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(ma);
*mb++ = (int32_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
int32_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
*mb++ = (int32_t)(*ma++);
}
}
break;
case TIFF_LONG8:
{
uint64_t *ma;
int32_t *mb;
uint32_t n;
ma = (uint64_t *)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_t)(*ma++);
}
}
break;
case TIFF_SLONG8:
{
int64_t *ma;
int32_t *mb;
uint32_t n;
ma = (int64_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)ma);
err = TIFFReadDirEntryCheckRangeSlongSlong8(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (int32_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong8ArrayWithLimit(TIFF *tif, TIFFDirEntry *direntry,
uint64_t **value, uint64_t maxcount)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
uint64_t *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_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8(*value, count);
return (TIFFReadDirEntryErrOk);
case TIFF_SLONG8:
{
int64_t *m;
uint32_t n;
m = (int64_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8((uint64_t *)m);
err = TIFFReadDirEntryCheckRangeLong8Slong8(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (uint64_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
}
data = (uint64_t *)_TIFFmallocExt(tif, count * 8);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
uint64_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (uint64_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
uint64_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
err = TIFFReadDirEntryCheckRangeLong8Sbyte(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint64_t)(*ma++);
}
}
break;
case TIFF_SHORT:
{
uint16_t *ma;
uint64_t *mb;
uint32_t n;
ma = (uint16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(ma);
*mb++ = (uint64_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
uint64_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
err = TIFFReadDirEntryCheckRangeLong8Sshort(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint64_t)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
uint64_t *mb;
uint32_t n;
ma = (uint32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong(ma);
*mb++ = (uint64_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
uint64_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
err = TIFFReadDirEntryCheckRangeLong8Slong(*ma);
if (err != TIFFReadDirEntryErrOk)
break;
*mb++ = (uint64_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, data);
return (err);
}
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryLong8Array(TIFF *tif, TIFFDirEntry *direntry, uint64_t **value)
{
return TIFFReadDirEntryLong8ArrayWithLimit(tif, direntry, value,
~((uint64_t)0));
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntrySlong8Array(TIFF *tif, TIFFDirEntry *direntry, int64_t **value)
{
enum TIFFReadDirEntryErr err;
uint32_t count;
void *origdata;
int64_t *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_t *m;
uint32_t n;
m = (uint64_t *)origdata;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong8(m);
err = TIFFReadDirEntryCheckRangeSlong8Long8(*m);
if (err != TIFFReadDirEntryErrOk)
{
_TIFFfreeExt(tif, origdata);
return (err);
}
m++;
}
*value = (int64_t *)origdata;
return (TIFFReadDirEntryErrOk);
}
case TIFF_SLONG8:
*value = (int64_t *)origdata;
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabArrayOfLong8((uint64_t *)(*value), count);
return (TIFFReadDirEntryErrOk);
}
data = (int64_t *)_TIFFmallocExt(tif, count * 8);
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
int64_t *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int64_t)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
int64_t *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (int64_t)(*ma++);
}
break;
case TIFF_SHORT:
{
uint16_t *ma;
int64_t *mb;
uint32_t n;
ma = (uint16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort(ma);
*mb++ = (int64_t)(*ma++);
}
}
break;
case TIFF_SSHORT:
{
int16_t *ma;
int64_t *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
*mb++ = (int64_t)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
int64_t *mb;
uint32_t n;
ma = (uint32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong(ma);
*mb++ = (int64_t)(*ma++);
}
}
break;
case TIFF_SLONG:
{
int32_t *ma;
int64_t *mb;
uint32_t n;
ma = (int32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong((uint32_t *)ma);
*mb++ = (int64_t)(*ma++);
}
}
break;
}
_TIFFfreeExt(tif, origdata);
*value = data;
return (TIFFReadDirEntryErrOk);
}
static enum TIFFReadDirEntryErr
TIFFReadDirEntryFloatArray(TIFF *tif, TIFFDirEntry *direntry, float **value)
{
enum TIFFReadDirEntryErr err;
uint32_t 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_t *)origdata, count);
TIFFCvtIEEEDoubleToNative(tif, count, (float *)origdata);
*value = (float *)origdata;
return (TIFFReadDirEntryErrOk);
}
data = (float *)_TIFFmallocExt(tif, count * sizeof(float));
if (data == 0)
{
_TIFFfreeExt(tif, origdata);
return (TIFFReadDirEntryErrAlloc);
}
switch (direntry->tdir_type)
{
case TIFF_BYTE:
{
uint8_t *ma;
float *mb;
uint32_t n;
ma = (uint8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (float)(*ma++);
}
break;
case TIFF_SBYTE:
{
int8_t *ma;
float *mb;
uint32_t n;
ma = (int8_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
*mb++ = (float)(*ma++);
}
break;
case TIFF_SHORT:
{
uint16_t *ma;
float *mb;
uint32_t n;
ma = (uint16_t *)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_t *ma;
float *mb;
uint32_t n;
ma = (int16_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabShort((uint16_t *)ma);
*mb++ = (float)(*ma++);
}
}
break;
case TIFF_LONG:
{
uint32_t *ma;
float *mb;
uint32_t n;
ma = (uint32_t *)origdata;
mb = data;
for (n = 0; n < count; n++)
{
if (tif->tif_flags & TIFF_SWAB)
TIFFSwabLong(ma);
*mb++ = (float)(*ma++);
}
}
break;
case