diff --git a/OpenEXR/IlmImf/ImfDeepScanLineInputFile.cpp b/OpenEXR/IlmImf/ImfDeepScanLineInputFile.cpp index 3d61c0fd2..e95985a94 100644 --- a/OpenEXR/IlmImf/ImfDeepScanLineInputFile.cpp +++ b/OpenEXR/IlmImf/ImfDeepScanLineInputFile.cpp @@ -344,6 +344,17 @@ reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset); OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); //next is unpacked sample table size - skip this too + + // check for bad values to prevent overflow + if (packed_offset < 0 || + packed_sample < 0 || + (INT64_MAX-packed_offset < packed_sample ) || + (INT64_MAX-(packed_offset+packed_sample) < 8 ) ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } + + Xdr::skip (is, packed_offset+packed_sample+8); if (lineOrder == INCREASING_Y) diff --git a/OpenEXR/IlmImf/ImfMultiPartInputFile.cpp b/OpenEXR/IlmImf/ImfMultiPartInputFile.cpp index 97233ce2b..07a6ff936 100644 --- a/OpenEXR/IlmImf/ImfMultiPartInputFile.cpp +++ b/OpenEXR/IlmImf/ImfMultiPartInputFile.cpp @@ -655,6 +655,11 @@ MultiPartInputFile::Data::chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPA OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); //add 40 byte header to packed sizes (tile coordinates, packed sizes, unpacked size) + // check for bad values to prevent overflow + if ( (INT64_MAX - packed_offset < packed_sample) || ( INT64_MAX - (packed_offset + packed_sample) < 40ll) ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } size_of_chunk=packed_offset+packed_sample + 40ll; } else @@ -663,6 +668,12 @@ MultiPartInputFile::Data::chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPA // regular image has 20 bytes of header, 4 byte chunksize; int chunksize; OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, chunksize); + // check for bad values to prevent overflow + if ( chunksize < 0 ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } + size_of_chunk=static_cast(chunksize) + 20ll; } } @@ -692,14 +703,27 @@ MultiPartInputFile::Data::chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPA Int64 packed_sample; OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset); OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample); - - + + // check for bad values to prevent overflow + if ( packed_offset < 0 || + packed_sample < 0 || + (INT64_MAX - packed_offset < packed_sample) || + ( INT64_MAX - (packed_offset + packed_sample) < 28ll) ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } size_of_chunk=packed_offset+packed_sample + 28ll; } else { int chunksize; OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, chunksize); + + // check for bad values to prevent overflow + if ( chunksize < 0 ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } size_of_chunk=static_cast(chunksize) + 8ll; } @@ -709,7 +733,11 @@ MultiPartInputFile::Data::chunkOffsetReconstruction(OPENEXR_IMF_INTERNAL_NAMESPA { chunk_start+=4; } - + + if ( (INT64_MAX - chunk_start) < size_of_chunk ) + { + throw IEX_NAMESPACE::IoExc("File pointer overflow during reconstruction"); + } chunk_start+=size_of_chunk; is.seekg(chunk_start); diff --git a/OpenEXR/IlmImf/ImfScanLineInputFile.cpp b/OpenEXR/IlmImf/ImfScanLineInputFile.cpp index 995f7721b..b10d4c21d 100644 --- a/OpenEXR/IlmImf/ImfScanLineInputFile.cpp +++ b/OpenEXR/IlmImf/ImfScanLineInputFile.cpp @@ -306,6 +306,11 @@ reconstructLineOffsets (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int dataSize; OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, dataSize); + // check for bad values to prevent overflow + if ( dataSize < 0 ) + { + throw IEX_NAMESPACE::IoExc("Invalid chunk size"); + } Xdr::skip (is, dataSize); if (lineOrder == INCREASING_Y) diff --git a/OpenEXR/IlmImf/ImfTileOffsets.cpp b/OpenEXR/IlmImf/ImfTileOffsets.cpp index 815b88f99..428446915 100644 --- a/OpenEXR/IlmImf/ImfTileOffsets.cpp +++ b/OpenEXR/IlmImf/ImfTileOffsets.cpp @@ -150,14 +150,30 @@ TileOffsets::findTiles (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, bool isMult OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_offset_table_size); OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, packed_sample_size); + // check for bad values to prevent overflow + if ( packed_offset_table_size < 0 || + packed_sample_size < 0 || + ( INT64_MAX - packed_offset_table_size < packed_sample_size) || + ( INT64_MAX - (packed_offset_table_size + packed_sample_size) ) < 8 ) + { + throw IEX_NAMESPACE::IoExc("Invalid deep tile size"); + } + // next Int64 is unpacked sample size - skip that too Xdr::skip (is, packed_offset_table_size+packed_sample_size+8); - }else{ - - int dataSize; + } + else + { + int dataSize; OPENEXR_IMF_INTERNAL_NAMESPACE::Xdr::read (is, dataSize); + // check for bad values to prevent overflow + if ( dataSize < 0 ) + { + throw IEX_NAMESPACE::IoExc("Invalid tile size"); + } + Xdr::skip (is, dataSize); } if (skipOnly) continue;