Skip to content

Commit

Permalink
Fixed crash with cloud optimized geotiffs(COGs) accessing wrong image
Browse files Browse the repository at this point in the history
file directories(IFDs).
  • Loading branch information
David Burken committed Nov 9, 2021
1 parent 983fa4e commit 1887286
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 33 deletions.
3 changes: 3 additions & 0 deletions include/ossim/imaging/ossimTiffTileSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,10 @@ class OSSIMDLLEXPORT ossimTiffTileSource : public ossimImageHandler
std::vector<ossim_uint16> thePlanarConfig;
std::vector<ossim_uint16> thePhotometric;
std::vector<ossim_uint32> theRowsPerStrip;

// Holds the image file directory(IFD) for each image/mask level.
std::vector<ossim_uint32> theImageDirectoryList;
std::vector<ossim_uint32> theMaskDirectoryList;

/** theInputTileSize reflects the most efficient tiling scheme for reading from disk. If the
* image is tiled, then the output tile size will match the tiling on disk. If it is stripped,
Expand Down
9 changes: 6 additions & 3 deletions include/ossim/support_data/TiffHandlerState.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,12 @@ namespace ossim
bool getMinSampleValue(ossim_float64 &minSampleValue, ossim_int32 directory = 0) const;
bool getMaxSampleValue(ossim_float64 &maxSampleValue, ossim_int32 directory = 0) const;
bool hasColorMap(ossim_int32 dir)const;
bool isReduced(ossim_int32 directory = 0) const;
bool isPage(ossim_int32 directory = 0) const;
bool isMask(ossim_int32 directory = 0) const;

// Overloaded for int not called from baseline.
// bool isReduced(ossim_int32 directory = 0) const;
// bool isPage(ossim_int32 directory = 0) const;
// bool isMask(ossim_int32 directory = 0) const;

bool isDigitalGlobe()const;
ossim_int32 getSubFileType(ossim_int32 directory = 0) const;
ossim_uint32 getNumberOfDirectories()const;
Expand Down
85 changes: 63 additions & 22 deletions src/imaging/ossimTiffTileSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ ossimTiffTileSource::ossimTiffTileSource()
thePhotometric(0),
theRowsPerStrip(0),
theImageDirectoryList(0),
theMaskDirectoryList(0),
theCurrentTiffRlevel(0),
theCompressionType(0),
theOutputBandList(0)
Expand Down Expand Up @@ -206,7 +207,7 @@ bool ossimTiffTileSource::getTile(ossimImageData *result,
reallocateBuffer = true;
}

if (getCurrentTiffRLevel() != theImageDirectoryList[level])
if (theCurrentDirectory != theImageDirectoryList[level])
{
status = setTiffDirectory(theImageDirectoryList[level]);
if (status)
Expand Down Expand Up @@ -405,6 +406,7 @@ bool ossimTiffTileSource::open(std::shared_ptr<ossim::istream> &str,
}
theImageFile = ossimFilename(connectionString);
theImageDirectoryList.clear();
theMaskDirectoryList.clear();

//---
// Note: The 'm' in "rm" is to tell TIFFOpen to not memory map the file.
Expand Down Expand Up @@ -556,29 +558,42 @@ bool ossimTiffTileSource::open(std::shared_ptr<ossim::istream> &str,
<< endl;
}

if (state->isReduced(dir))
if (dir != 0)
{
//---
// Check for a thumbnail image. If present don't use as it will mess with
// overviews. Currently only checking if it's a two directory image, i.e. a full
// res and a thumbnail.
//
// Note this shuts off the thumbnail which someone may want to see. We could make
// this a reader prop if it becomes an issue. drb - 09 Jan. 2012.
//---
if (dir != 0)
if (state->isReduced(dir))
{
//---
// Check for a thumbnail image. If present don't use as it will mess with
// overviews. Currently only checking if it's a two directory image, i.e. a full
// res and a thumbnail.
//
// Note this shuts off the thumbnail which someone may want to see. We could make
// this a reader prop if it becomes an issue. drb - 09 Jan. 2012.
//---
bool acceptAsRrdsLayer = true;
if ((theNumberOfDirectories == 2) && (dir == 1))
{
acceptAsRrdsLayer = isPowerOfTwoDecimation(dir);
}

if (acceptAsRrdsLayer)
{
theImageDirectoryList.push_back(dir);
}
}
else if ( (state->getSubFileType(dir) == FILETYPE_MASK) ||
(state->getSubFileType(dir) == 5) )
{
// sub_file_type of 5(bit mask) is not in tiff.h yet.
theMaskDirectoryList.push_back(dir);
}
else
{
ossimNotify(ossimNotifyLevel_WARN)
<< MODULE << " WARNING:\nUnhandled sub file type value!"
<< "IFD: " << dir << " sub file type: " << state->getSubFileType(dir)
<< std::endl;
}
}

thePlanarConfig[dir] = state->getPlanarConfig(dir);
Expand Down Expand Up @@ -1030,7 +1045,8 @@ bool ossimTiffTileSource::loadFromScanLine(const ossimIrect &clip_rect,
ossimInterleaveType type =
(thePlanarConfig[theCurrentDirectory] == PLANARCONFIG_CONTIG) ? OSSIM_BIP : OSSIM_BIL;

if (theBufferRLevel != getCurrentTiffRLevel() || !clip_rect.completely_within(theBufferRect))
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
//***
// Must reload the buffer. Grab enough lines to fill the depth of the
Expand Down Expand Up @@ -1318,7 +1334,7 @@ bool ossimTiffTileSource::loadFromRgbaU8Tile(const ossimIrect &tile_rect,
ulTilePt.y +
theInputTileSize[theCurrentDirectory].y - 1);

if (getCurrentTiffRLevel() != theBufferRLevel ||
if (theBufferRLevel != getCurrentTiffRLevel() ||
tiff_tile_rect != theBufferRect)
{
// Need to grab a new tile.
Expand Down Expand Up @@ -1466,8 +1482,8 @@ bool ossimTiffTileSource::loadFromRgbaU8Strip(const ossimIrect &tile_rect,
// Loop through strips...
for (ossim_uint32 strip = starting_strip; strip <= ending_strip; strip++)
{
if ((theBufferRLevel != theCurrentDirectory) ||
(clip_rect.completely_within(theBufferRect) == false))
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
if (TIFFReadRGBAStrip(theTiffPtr,
(strip * theRowsPerStrip[theCurrentDirectory]),
Expand All @@ -1480,7 +1496,7 @@ bool ossimTiffTileSource::loadFromRgbaU8Strip(const ossimIrect &tile_rect,
}

// Capture rect and rlevel of buffer:
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();
theBufferRect = ossimIrect(
0,
starting_strip,
Expand Down Expand Up @@ -1730,7 +1746,7 @@ bool ossimTiffTileSource::loadFromU16Strip(const ossimIrect &clip_rect, ossimIma
// Loop through strips....
for (ossim_uint32 strip = starting_strip; strip <= ending_strip; ++strip)
{
if ((theBufferRLevel != theCurrentDirectory) ||
if (theBufferRLevel != getCurrentTiffRLevel() ||
!clip_rect.completely_within(theBufferRect))
{
// Fill buffer block:
Expand Down Expand Up @@ -1788,7 +1804,7 @@ bool ossimTiffTileSource::loadFromU16Strip(const ossimIrect &clip_rect, ossimIma
if (status)
{
// Capture rect and rlevel of buffer:
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();
theBufferRect = ossimIrect(0,
startY,
theImageWidth[theCurrentDirectory] - 1,
Expand Down Expand Up @@ -2059,9 +2075,10 @@ std::ostream &ossimTiffTileSource::print(std::ostream &os) const
<< "\nmin_sample_value: " << theMinSampleValue
<< "\nmax_sample_value: " << theMaxSampleValue
<< "\nnull_sample_value: " << theNullSampleValue
<< "\nr0_is_full_res: " << theR0isFullRes
<< "\ntheNumberOfDirectories: " << theNumberOfDirectories
<< "\nr0_is_full_res: " << theR0isFullRes;

<< "\nimage_dirs: " << theImageDirectoryList.size();
for (ossim_uint32 i = 0; i < theNumberOfDirectories; ++i)
{
os << "\ndirectory[" << i << "]"
Expand All @@ -2085,6 +2102,30 @@ std::ostream &ossimTiffTileSource::print(std::ostream &os) const
os << endl;
}

os << "\nmask_dirs: " << theMaskDirectoryList.size();
for (ossim_uint32 i=0; i<(ossim_uint32)theMaskDirectoryList.size(); ++i )
{
ossim_uint32 ifdIndex = theMaskDirectoryList[i];
os << "\nmask_ifd_index: " << ifdIndex
<< "\nmask_width: " << theImageWidth[ifdIndex]
<< "\nmask_length: " << theImageLength[ifdIndex]
<< "\nmask_read method: " << getReadMethod(ifdIndex).c_str()
<< "\nmask_planar: " << thePlanarConfig[ifdIndex]
<< "\nmask_photometric: " << thePhotometric[ifdIndex];
if (theRowsPerStrip[ifdIndex])
{
os << "\nmask_rows_per_strip: " << theRowsPerStrip[ifdIndex];
}
if (theInputTileSize[i].x)
{
os << "\nmask_tile_width: " << theInputTileSize[i].x;
}
if (theInputTileSize[i].y)
{
os << "\nmask_tile_length: " << theInputTileSize[i].y;
}
}

if (theTile.valid())
{
os << "\nOutput tile dump:\n"
Expand Down Expand Up @@ -2665,7 +2706,7 @@ bool ossimTiffTileSource::allocateBuffer()
}

theBufferRect.makeNan();
theBufferRLevel = theCurrentDirectory;
theBufferRLevel = getCurrentTiffRLevel();

if (bSuccess && (buffer_size != theBufferSize))
{
Expand Down
28 changes: 20 additions & 8 deletions src/support_data/TiffHandlerState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void ossim::TiffHandlerState::loadDefaults(std::shared_ptr<ossim::istream> &str,
m_tags.getSortedList(prefixValues, "tiff.image");
nValues = prefixValues.size();
addValue("tiff.number_of_directories", ossimString::toString(nValues));
ossim_uint32 idx = 0;
// ossim_uint32 idx = 0;
//ossim_int64 h = getImageLength(0);
//ossim_int64 w = getImageWidth(0);
ossim_int64 tw = getTileWidth(0);
Expand Down Expand Up @@ -222,13 +222,13 @@ void ossim::TiffHandlerState::loadDirectory(TIFF* tiffPtr,
{
ossim_uint32 imageWidth=0;
ossim_uint32 imageLength=0;
ossim_int32 readMethod=0;
// ossim_int32 readMethod=0;
ossim_uint16 planarConfig=0;
ossim_uint16 photometric=0;
ossim_uint32 rowsPerStrip=0;
ossim_uint32 imageTileWidth=0;
ossim_uint32 imageTileLength=0;
ossim_uint32 imageDirectoryList=0;
// ossim_uint32 imageDirectoryList=0;
ossim_int32 compressionType=0;
ossim_uint32 subFileType=0;
ossim_uint16 bitsPerSample=0;
Expand Down Expand Up @@ -435,7 +435,7 @@ void ossim::TiffHandlerState::loadGeotiffTags(TIFF* tiffPtr,
ossim_uint16 rasterType = 0;
ossim_uint16 pcsCode = 0;
ossim_uint16 coordTransGeoCode = 0;
ossim_uint32 idx = 0;
// ossim_uint32 idx = 0;
GTIF* gtif = GTIFNew(tiffPtr);
char citationStrPtr[CITATION_STRING_SIZE];
char* buf = 0;
Expand Down Expand Up @@ -693,17 +693,27 @@ bool ossim::TiffHandlerState::isDigitalGlobe() const

bool ossim::TiffHandlerState::isReduced(ossim_uint32 directory)const
{
return getSubFileType(directory)&FILETYPE_REDUCEDIMAGE;
// return getSubFileType(directory) & FILETYPE_REDUCEDIMAGE;
return getSubFileType(directory) == FILETYPE_REDUCEDIMAGE;
}

bool ossim::TiffHandlerState::isMask(ossim_uint32 directory)const
{
return getSubFileType(directory) & FILETYPE_MASK;
//---
// NOTE:
// sub_file_type of 5(bit mask) from cloud optimized geotiff(COG) sample
// is not in tiff.h yet. Not sure if it's standard yet. drb - 20211109
//---

// return getSubFileType(directory) & FILETYPE_MASK;
ossim_int32 sub_file_type = getSubFileType(directory);
return (sub_file_type == FILETYPE_MASK) || (sub_file_type == 5);
}

bool ossim::TiffHandlerState::isPage(ossim_uint32 directory)const
{
return getSubFileType(directory) & FILETYPE_PAGE;
// return getSubFileType(directory) & FILETYPE_PAGE;
return getSubFileType(directory) == FILETYPE_PAGE;
}

bool ossim::TiffHandlerState::isTiled(ossim_uint32 directory)const
Expand All @@ -717,7 +727,7 @@ void ossim::TiffHandlerState::convertArrayToStringList(ossimString& result, doub
result = "";
if(doubleArray && (doubleArraySize > 0))
{
ossim_int32 precision = 20;
// ossim_int32 precision = 20;
std::ostringstream doubleArrayStream;
doubleArrayStream << "(";
for(idx = 0; idx < doubleArraySize-1;++idx)
Expand Down Expand Up @@ -950,6 +960,7 @@ bool ossim::TiffHandlerState::hasColorMap(ossim_int32 directory)const
return exists(directory, "colormap");
}

#if 0 /* Overloaded methods for int32 dir not called in core. */
bool ossim::TiffHandlerState::isReduced(ossim_int32 directory) const
{

Expand All @@ -965,6 +976,7 @@ bool ossim::TiffHandlerState::isMask(ossim_int32 directory) const
{
return getSubFileType(directory) == FILETYPE_MASK;
}
#endif

ossim_int32 ossim::TiffHandlerState::getSubFileType(ossim_int32 directory) const
{
Expand Down

0 comments on commit 1887286

Please sign in to comment.