Skip to content

Commit bb734e3

Browse files
authored
Merge pull request OSGeo#13598 from rouault/jpeg_and_exif_large_offsets
JPEG/EXIF: make them handle large offsets
2 parents 6b5da04 + 4c28078 commit bb734e3

File tree

8 files changed

+76
-76
lines changed

8 files changed

+76
-76
lines changed

frmts/avif/avifdataset.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -592,16 +592,16 @@ bool GDALAVIFDataset::Init(GDALOpenInfo *poOpenInfo)
592592
VSILFILE *fpEXIF =
593593
VSIFileFromMemBuffer(nullptr, m_decoder->image->exif.data,
594594
m_decoder->image->exif.size, false);
595-
int nExifOffset = 0;
596-
int nInterOffset = 0;
597-
int nGPSOffset = 0;
595+
uint32_t nExifOffset = 0;
596+
uint32_t nInterOffset = 0;
597+
uint32_t nGPSOffset = 0;
598598
char **papszEXIFMetadata = nullptr;
599599
#ifdef CPL_LSB
600600
const bool bSwab = m_decoder->image->exif.data[0] == 0x4d;
601601
#else
602602
const bool bSwab = m_decoder->image->exif.data[0] == 0x49;
603603
#endif
604-
constexpr int nTIFFHEADER = 0;
604+
constexpr uint32_t nTIFFHEADER = 0;
605605
uint32_t nTiffDirStart;
606606
memcpy(&nTiffDirStart, m_decoder->image->exif.data + 4,
607607
sizeof(uint32_t));

frmts/gtiff/gtiffdataset_read.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,24 +6599,24 @@ void GTiffDataset::LoadEXIFMetadata()
65996599
const bool bSwabflag = bLittleEndian != bLeastSignificantBit; // != is XOR.
66006600

66016601
char **papszMetadata = nullptr;
6602-
toff_t nOffset = 0; // TODO(b/28199387): Refactor to simplify casting.
6602+
toff_t nOffset = 0;
66036603

66046604
if (TIFFGetField(m_hTIFF, TIFFTAG_EXIFIFD, &nOffset))
66056605
{
6606-
int nExifOffset = static_cast<int>(nOffset);
6607-
int nInterOffset = 0;
6608-
int nGPSOffset = 0;
6609-
EXIFExtractMetadata(papszMetadata, fp, static_cast<int>(nOffset),
6606+
uint32_t nExifOffset = static_cast<uint32_t>(nOffset);
6607+
uint32_t nInterOffset = 0;
6608+
uint32_t nGPSOffset = 0;
6609+
EXIFExtractMetadata(papszMetadata, fp, static_cast<uint32_t>(nOffset),
66106610
bSwabflag, 0, nExifOffset, nInterOffset,
66116611
nGPSOffset);
66126612
}
66136613

66146614
if (TIFFGetField(m_hTIFF, TIFFTAG_GPSIFD, &nOffset))
66156615
{
6616-
int nExifOffset = 0; // TODO(b/28199387): Refactor to simplify casting.
6617-
int nInterOffset = 0;
6618-
int nGPSOffset = static_cast<int>(nOffset);
6619-
EXIFExtractMetadata(papszMetadata, fp, static_cast<int>(nOffset),
6616+
uint32_t nExifOffset = 0;
6617+
uint32_t nInterOffset = 0;
6618+
uint32_t nGPSOffset = static_cast<uint32_t>(nOffset);
6619+
EXIFExtractMetadata(papszMetadata, fp, static_cast<uint32_t>(nOffset),
66206620
bSwabflag, 0, nExifOffset, nInterOffset,
66216621
nGPSOffset);
66226622
}

frmts/heif/heifdataset.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,15 +460,15 @@ void GDALHEIFDataset::ReadMetadata()
460460
constexpr bool bLSBPlatform = CPL_IS_LSB != 0;
461461
const bool bSwabflag = bLittleEndianTIFF != bLSBPlatform;
462462

463-
int nTIFFDirOff;
463+
uint32_t nTIFFDirOff;
464464
memcpy(&nTIFFDirOff, &data[nTIFFFileOffset + 4], 4);
465465
if (bSwabflag)
466466
{
467467
CPL_SWAP32PTR(&nTIFFDirOff);
468468
}
469-
int nExifOffset = 0;
470-
int nInterOffset = 0;
471-
int nGPSOffset = 0;
469+
uint32_t nExifOffset = 0;
470+
uint32_t nInterOffset = 0;
471+
uint32_t nGPSOffset = 0;
472472
EXIFExtractMetadata(papszMD, fpTemp, nTIFFDirOff, bSwabflag, 0,
473473
nExifOffset, nInterOffset, nGPSOffset);
474474
if (nExifOffset > 0)

frmts/jpeg/jpgdataset.cpp

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "jpgdataset.h"
1919

2020
#include <cerrno>
21+
#include <cinttypes>
2122
#include <climits>
2223
#include <cstddef>
2324
#include <cstdio>
@@ -149,7 +150,7 @@ void JPGDatasetCommon::ReadImageStructureMetadata()
149150
const vsi_l_offset nCurOffset = VSIFTellL(m_fpImage);
150151

151152
GByte abyChunkHeader[4];
152-
int nChunkLoc = 2;
153+
vsi_l_offset nChunkLoc = 2;
153154
constexpr GByte MARKER_QUANT_TABLE = 0xDB;
154155
struct CPLMD5Context context;
155156
CPLMD5Init(&context);
@@ -331,7 +332,7 @@ void JPGDatasetCommon::ReadXMPMetadata()
331332
constexpr int APP1_XMP_SIGNATURE_LEN =
332333
static_cast<int>(sizeof(APP1_XMP_SIGNATURE));
333334
GByte abyChunkHeader[JFIF_MARKER_SIZE + APP1_XMP_SIGNATURE_LEN] = {};
334-
int nChunkLoc = 2;
335+
vsi_l_offset nChunkLoc = 2;
335336
bool bFoundXMP = false;
336337

337338
while (true)
@@ -433,7 +434,7 @@ void JPGDatasetCommon::ReadDJIMetadata()
433434

434435
const vsi_l_offset nCurOffset = VSIFTellL(m_fpImage);
435436

436-
int nChunkLoc = 2;
437+
vsi_l_offset nChunkLoc = 2;
437438
// size of APP1 segment marker"
438439
GByte abyChunkHeader[4];
439440

@@ -552,7 +553,7 @@ void JPGDatasetCommon::ReadFLIRMetadata()
552553
// Save current position to avoid disturbing JPEG stream decoding.
553554
const vsi_l_offset nCurOffset = VSIFTellL(m_fpImage);
554555

555-
int nChunkLoc = 2;
556+
vsi_l_offset nChunkLoc = 2;
556557
// size of APP1 segment marker + size of "FLIR\0"
557558
GByte abyChunkHeader[4 + 5];
558559
std::vector<GByte> abyFLIR;
@@ -1198,7 +1199,7 @@ void JPGDatasetCommon::ReadICCProfile()
11981199

11991200
// Search for APP2 chunk.
12001201
GByte abyChunkHeader[18] = {};
1201-
int nChunkLoc = 2;
1202+
vsi_l_offset nChunkLoc = 2;
12021203
bool bOk = true;
12031204

12041205
while (true)
@@ -1378,10 +1379,9 @@ void JPGDatasetCommon::ReadICCProfile()
13781379
/************************************************************************/
13791380
bool JPGDatasetCommon::EXIFInit(VSILFILE *fp)
13801381
{
1381-
if (nTiffDirStart == 0)
1382-
return false;
1383-
if (nTiffDirStart > 0)
1384-
return true;
1382+
if (m_bTiffDirStartInit)
1383+
return nTiffDirStart > 0;
1384+
m_bTiffDirStartInit = true;
13851385
nTiffDirStart = 0;
13861386

13871387
#ifdef CPL_MSB
@@ -1392,7 +1392,7 @@ bool JPGDatasetCommon::EXIFInit(VSILFILE *fp)
13921392

13931393
// Search for APP1 chunk.
13941394
GByte abyChunkHeader[10] = {};
1395-
int nChunkLoc = 2;
1395+
vsi_l_offset nChunkLoc = 2;
13961396

13971397
while (true)
13981398
{
@@ -1431,25 +1431,27 @@ bool JPGDatasetCommon::EXIFInit(VSILFILE *fp)
14311431
STARTS_WITH(reinterpret_cast<char *>(abyChunkHeader) + 4,
14321432
"Exif"))
14331433
{
1434-
if (nTIFFHEADER < 0)
1434+
if (nTIFFHEADER == 0)
14351435
{
14361436
nTIFFHEADER = nChunkLoc + 10;
14371437
}
14381438
else
14391439
{
1440-
CPLDebug(
1441-
"JPEG",
1442-
"Another Exif directory found at offset %u. Ignoring "
1443-
"it and only taking into account the one at offset %u",
1444-
unsigned(nChunkLoc + 10), unsigned(nTIFFHEADER));
1440+
CPLDebug("JPEG",
1441+
"Another Exif directory found at offset %" PRIu64
1442+
". Ignoring "
1443+
"it and only taking into account the one at "
1444+
"offset %" PRIu64,
1445+
static_cast<uint64_t>(nChunkLoc + 10),
1446+
static_cast<uint64_t>(nTIFFHEADER));
14451447
}
14461448
}
14471449
}
14481450

14491451
nChunkLoc += 2 + nChunkLength;
14501452
}
14511453

1452-
if (nTIFFHEADER < 0)
1454+
if (nTIFFHEADER == 0)
14531455
return false;
14541456

14551457
// Read TIFF header.
@@ -1897,8 +1899,7 @@ GDALDataset *JPGDatasetCommon::InitEXIFOverview()
18971899

18981900
// Read number of entry in directory.
18991901
GUInt16 nEntryCount = 0;
1900-
if (nTiffDirStart > (INT_MAX - nTIFFHEADER) ||
1901-
VSIFSeekL(m_fpImage, nTiffDirStart + nTIFFHEADER, SEEK_SET) != 0 ||
1902+
if (VSIFSeekL(m_fpImage, nTiffDirStart + nTIFFHEADER, SEEK_SET) != 0 ||
19021903
VSIFReadL(&nEntryCount, 1, sizeof(GUInt16), m_fpImage) !=
19031904
sizeof(GUInt16))
19041905
{
@@ -1930,7 +1931,7 @@ GDALDataset *JPGDatasetCommon::InitEXIFOverview()
19301931
return nullptr;
19311932
if (bSwabflag)
19321933
CPL_SWAP32PTR(&nNextDirOff);
1933-
if (nNextDirOff == 0 || nNextDirOff > UINT_MAX - nTIFFHEADER)
1934+
if (nNextDirOff == 0)
19341935
return nullptr;
19351936

19361937
// Seek to IFD1.
@@ -1939,8 +1940,8 @@ GDALDataset *JPGDatasetCommon::InitEXIFOverview()
19391940
sizeof(GUInt16))
19401941
{
19411942
CPLError(CE_Failure, CPLE_AppDefined,
1942-
"Error reading IFD1 Directory count at %d.",
1943-
nTIFFHEADER + nNextDirOff);
1943+
"Error reading IFD1 Directory count at %" PRIu64 ".",
1944+
static_cast<uint64_t>(nTIFFHEADER + nNextDirOff));
19441945
return nullptr;
19451946
}
19461947

@@ -2012,14 +2013,15 @@ GDALDataset *JPGDatasetCommon::InitEXIFOverview()
20122013
}
20132014
if (nCompression != 6 || nImageWidth >= nRasterXSize ||
20142015
nImageHeight >= nRasterYSize || nJpegIFOffset == 0 ||
2015-
nJpegIFOffset > UINT_MAX - nTIFFHEADER ||
2016+
nTIFFHEADER > UINT_MAX || nJpegIFOffset > UINT_MAX - nTIFFHEADER ||
20162017
static_cast<int>(nJpegIFByteCount) <= 0)
20172018
{
20182019
return nullptr;
20192020
}
20202021

20212022
const char *pszSubfile =
2022-
CPLSPrintf("JPEG_SUBFILE:%u,%d,%s", nTIFFHEADER + nJpegIFOffset,
2023+
CPLSPrintf("JPEG_SUBFILE:%" PRIu64 ",%d,%s",
2024+
static_cast<uint64_t>(nTIFFHEADER + nJpegIFOffset),
20232025
nJpegIFByteCount, GetDescription());
20242026
JPGDatasetOpenArgs sArgs;
20252027
sArgs.pszFilename = pszSubfile;

frmts/jpeg/jpgdataset.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,13 @@ class JPGDatasetCommon CPL_NON_FINAL : public GDALPamDataset
171171
bool bHasReadDJIMetadata = false;
172172
bool bHasReadImageStructureMetadata = false;
173173
char **papszMetadata{};
174-
int nExifOffset{-1};
175-
int nInterOffset{-1};
176-
int nGPSOffset{-1};
174+
uint32_t nExifOffset{0};
175+
uint32_t nInterOffset{0};
176+
uint32_t nGPSOffset{0};
177177
bool bSwabflag{};
178-
int nTiffDirStart{-1};
179-
int nTIFFHEADER{-1};
178+
bool m_bTiffDirStartInit = false;
179+
uint32_t nTiffDirStart{0};
180+
vsi_l_offset nTIFFHEADER{0};
180181
bool bHasDoneJpegCreateDecompress{};
181182
bool bHasDoneJpegStartDecompress{};
182183

frmts/jpegxl/jpegxl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ bool JPEGXLDataset::Open(GDALOpenInfo *poOpenInfo)
360360
#else
361361
const bool bSwab = abyBoxBuffer[4] == 0x49;
362362
#endif
363-
constexpr int nTIFFHEADER = 0;
363+
constexpr uint32_t nTIFFHEADER = 0;
364364
uint32_t nTiffDirStart;
365365
memcpy(&nTiffDirStart, abyBoxBuffer.data() + 8,
366366
sizeof(uint32_t));
@@ -371,9 +371,9 @@ bool JPEGXLDataset::Open(GDALOpenInfo *poOpenInfo)
371371
VSILFILE *fpEXIF =
372372
VSIFileFromMemBuffer(nullptr, abyBoxBuffer.data() + 4,
373373
abyBoxBuffer.size() - 4, false);
374-
int nExifOffset = 0;
375-
int nInterOffset = 0;
376-
int nGPSOffset = 0;
374+
uint32_t nExifOffset = 0;
375+
uint32_t nInterOffset = 0;
376+
uint32_t nGPSOffset = 0;
377377
char **papszEXIFMetadata = nullptr;
378378
EXIFExtractMetadata(papszEXIFMetadata, fpEXIF, nTiffDirStart,
379379
bSwab, nTIFFHEADER, nExifOffset,

gcore/gdal_cpp_functions.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,11 @@ CPLString GDALFindAssociatedFile(const char *pszBasename, const char *pszExt,
237237
CSLConstList papszSiblingFiles, int nFlags);
238238

239239
CPLErr CPL_DLL EXIFExtractMetadata(char **&papszMetadata, void *fpL,
240-
int nOffset, int bSwabflag, int nTIFFHEADER,
241-
int &nExifOffset, int &nInterOffset,
242-
int &nGPSOffset);
240+
uint32_t nOffset, int bSwabflag,
241+
vsi_l_offset nTIFFHEADER,
242+
uint32_t &nExifOffset,
243+
uint32_t &nInterOffset,
244+
uint32_t &nGPSOffset);
243245

244246
int GDALValidateOpenOptions(GDALDriverH hDriver,
245247
const char *const *papszOptionOptions);

gcore/gdalexif.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -495,18 +495,18 @@ static int EXIF_TIFFDataWidth(int /* GDALEXIFTIFFDataType */ type)
495495
/* */
496496
/* Extract all entry from a IFD */
497497
/************************************************************************/
498-
CPLErr EXIFExtractMetadata(char **&papszMetadata, void *fpInL, int nOffset,
499-
int bSwabflag, int nTIFFHEADER, int &nExifOffset,
500-
int &nInterOffset, int &nGPSOffset)
498+
CPLErr EXIFExtractMetadata(char **&papszMetadata, void *fpInL, uint32_t nOffset,
499+
int bSwabflag, vsi_l_offset nTIFFHEADER,
500+
uint32_t &nExifOffset, uint32_t &nInterOffset,
501+
uint32_t &nGPSOffset)
501502
{
502503
/* -------------------------------------------------------------------- */
503504
/* Read number of entry in directory */
504505
/* -------------------------------------------------------------------- */
505506
GUInt16 nEntryCount;
506507
VSILFILE *const fp = static_cast<VSILFILE *>(fpInL);
507508

508-
if (nOffset > INT_MAX - nTIFFHEADER ||
509-
VSIFSeekL(fp, nOffset + nTIFFHEADER, SEEK_SET) != 0 ||
509+
if (VSIFSeekL(fp, nOffset + nTIFFHEADER, SEEK_SET) != 0 ||
510510
VSIFReadL(&nEntryCount, 1, sizeof(GUInt16), fp) != sizeof(GUInt16))
511511
{
512512
CPLError(CE_Failure, CPLE_AppDefined,
@@ -639,25 +639,20 @@ CPLErr EXIFExtractMetadata(char **&papszMetadata, void *fpInL, int nOffset,
639639
/* Save important directory tag offset */
640640
/* --------------------------------------------------------------------
641641
*/
642-
643-
// Our current API uses int32 and not uint32
644-
if (poTIFFDirEntry->tdir_offset < INT_MAX)
642+
if (poTIFFDirEntry->tdir_tag == EXIFOFFSETTAG)
645643
{
646-
if (poTIFFDirEntry->tdir_tag == EXIFOFFSETTAG)
647-
{
648-
nExifOffset = poTIFFDirEntry->tdir_offset;
649-
continue;
650-
}
651-
else if (poTIFFDirEntry->tdir_tag == INTEROPERABILITYOFFSET)
652-
{
653-
nInterOffset = poTIFFDirEntry->tdir_offset;
654-
continue;
655-
}
656-
else if (poTIFFDirEntry->tdir_tag == GPSOFFSETTAG)
657-
{
658-
nGPSOffset = poTIFFDirEntry->tdir_offset;
659-
continue;
660-
}
644+
nExifOffset = poTIFFDirEntry->tdir_offset;
645+
continue;
646+
}
647+
else if (poTIFFDirEntry->tdir_tag == INTEROPERABILITYOFFSET)
648+
{
649+
nInterOffset = poTIFFDirEntry->tdir_offset;
650+
continue;
651+
}
652+
else if (poTIFFDirEntry->tdir_tag == GPSOFFSETTAG)
653+
{
654+
nGPSOffset = poTIFFDirEntry->tdir_offset;
655+
continue;
661656
}
662657

663658
/* ----------------------------------------------------------------- */

0 commit comments

Comments
 (0)