From c072eb7c0f534c77e6d3c77e4e04a27508d50a54 Mon Sep 17 00:00:00 2001 From: wang_yue111 <648774160@qq.com> Date: Tue, 6 Apr 2021 15:37:31 +0800 Subject: [PATCH] fix CVE-2021-3474 CVE-2021-3477 CVE-2021-3476 CVE-2021-3475 CVE-2021-20296 CVE-2021-3479 CVE-2021-20296 --- CVE-2021-20296.patch | 26 ++ CVE-2021-3474.patch | 33 ++ CVE-2021-3475-pre0.patch | 27 ++ CVE-2021-3475-pre1.patch | 29 ++ CVE-2021-3475.patch | 35 ++ CVE-2021-3476.patch | 70 ++++ CVE-2021-3477.patch | 25 ++ CVE-2021-3478.patch | 35 ++ CVE-2021-3479-pre0.patch | 174 ++++++++++ CVE-2021-3479-pre1.patch | 171 ++++++++++ CVE-2021-3479-pre2.patch | 680 +++++++++++++++++++++++++++++++++++++++ CVE-2021-3479.patch | 550 +++++++++++++++++++++++++++++++ OpenEXR.spec | 16 +- 13 files changed, 1870 insertions(+), 1 deletion(-) create mode 100644 CVE-2021-20296.patch create mode 100644 CVE-2021-3474.patch create mode 100644 CVE-2021-3475-pre0.patch create mode 100644 CVE-2021-3475-pre1.patch create mode 100644 CVE-2021-3475.patch create mode 100644 CVE-2021-3476.patch create mode 100644 CVE-2021-3477.patch create mode 100644 CVE-2021-3478.patch create mode 100644 CVE-2021-3479-pre0.patch create mode 100644 CVE-2021-3479-pre1.patch create mode 100644 CVE-2021-3479-pre2.patch create mode 100644 CVE-2021-3479.patch diff --git a/CVE-2021-20296.patch b/CVE-2021-20296.patch new file mode 100644 index 0000000..7a64d1a --- /dev/null +++ b/CVE-2021-20296.patch @@ -0,0 +1,26 @@ +From 64ed1789afb3286cdb638bf34676f7d770032a84 Mon Sep 17 00:00:00 2001 +From: wang_yue111 <648774160@qq.com> +Date: Tue, 6 Apr 2021 10:24:35 +0800 +Subject: [PATCH] double-check unpackedBuffer created in DWA uncompress + +Signed-off-by: Peter Hillman +--- + IlmImf/ImfDwaCompressor.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/IlmImf/ImfDwaCompressor.cpp b/IlmImf/ImfDwaCompressor.cpp +index 2ef8878..c6518bb 100644 +--- a/IlmImf/ImfDwaCompressor.cpp ++++ b/IlmImf/ImfDwaCompressor.cpp +@@ -2524,7 +2524,7 @@ DwaCompressor::uncompress + + if (acCompressedSize > 0) + { +- if (totalAcUncompressedCount*sizeof(unsigned short) > _packedAcBufferSize) ++ if ( !_packedAcBuffer || totalAcUncompressedCount*sizeof(unsigned short) > _packedAcBufferSize) + { + throw Iex::InputExc("Error uncompressing DWA data" + "(corrupt header)."); +-- +2.23.0 + diff --git a/CVE-2021-3474.patch b/CVE-2021-3474.patch new file mode 100644 index 0000000..05916f9 --- /dev/null +++ b/CVE-2021-3474.patch @@ -0,0 +1,33 @@ +From c3ed4a1db1f39bf4524a644cb2af81dc8cfab33f Mon Sep 17 00:00:00 2001 +From: Peter Hillman +Date: Mon, 17 Aug 2020 12:29:03 +1200 +Subject: [PATCH] compute Huf codelengths using 64 bit to prevent shift + overflow + +Signed-off-by: Peter Hillman +--- + OpenEXR/IlmImf/ImfFastHuf.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/IlmImf/ImfFastHuf.cpp b/IlmImf/ImfFastHuf.cpp +index 9ccf2e15d..c04b56e75 100644 +--- a/IlmImf/ImfFastHuf.cpp ++++ b/IlmImf/ImfFastHuf.cpp +@@ -205,7 +205,7 @@ FastHufDecoder::FastHufDecoder + for (int l = _minCodeLength; l <= _maxCodeLength; ++l) + { + countTmp[l] = (double)codeCount[l] * +- (double)(2 << (_maxCodeLength-l)); ++ (double)(2ll << (_maxCodeLength-l)); + } + + for (int l = _minCodeLength; l <= _maxCodeLength; ++l) +@@ -215,7 +215,7 @@ FastHufDecoder::FastHufDecoder + for (int k =l + 1; k <= _maxCodeLength; ++k) + tmp += countTmp[k]; + +- tmp /= (double)(2 << (_maxCodeLength - l)); ++ tmp /= (double)(2ll << (_maxCodeLength - l)); + + base[l] = (Int64)ceil (tmp); + } diff --git a/CVE-2021-3475-pre0.patch b/CVE-2021-3475-pre0.patch new file mode 100644 index 0000000..490c833 --- /dev/null +++ b/CVE-2021-3475-pre0.patch @@ -0,0 +1,27 @@ +From d548fd5eb04d62ad65db18e6425a36e7ab6645dc Mon Sep 17 00:00:00 2001 +From: Cary Phillips +Date: Sat, 8 Aug 2020 16:27:03 -0700 +Subject: [PATCH] Avoid integer overflow in calculateNumTiles() + +Signed-off-by: Cary Phillips +--- + IlmImf/ImfTiledMisc.cpp | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/IlmImf/ImfTiledMisc.cpp b/IlmImf/ImfTiledMisc.cpp +index 8552ada20..1cff8037d 100644 +--- a/IlmImf/ImfTiledMisc.cpp ++++ b/IlmImf/ImfTiledMisc.cpp +@@ -301,7 +301,11 @@ calculateNumTiles (int *numTiles, + { + for (int i = 0; i < numLevels; i++) + { +- numTiles[i] = (levelSize (min, max, i, rmode) + size - 1) / size; ++ int l = levelSize (min, max, i, rmode); ++ if (l >= std::numeric_limits::max() - size + 1) ++ throw IEX_NAMESPACE::ArgExc ("Invalid size."); ++ ++ numTiles[i] = (l + size - 1) / size; + } + } + diff --git a/CVE-2021-3475-pre1.patch b/CVE-2021-3475-pre1.patch new file mode 100644 index 0000000..4d8f7d7 --- /dev/null +++ b/CVE-2021-3475-pre1.patch @@ -0,0 +1,29 @@ +From 46833b0e090a31cdccc32cad1ca27fe601d79875 Mon Sep 17 00:00:00 2001 +From: Cary Phillips +Date: Sat, 8 Aug 2020 16:34:02 -0700 +Subject: [PATCH] Change >= to > in overflow calculation + +Signed-off-by: Cary Phillips +--- + IlmImf/ImfTiledMisc.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/IlmImf/ImfTiledMisc.cpp b/IlmImf/ImfTiledMisc.cpp +index 1cff8037d..51b6e5c26 100644 +--- a/IlmImf/ImfTiledMisc.cpp ++++ b/IlmImf/ImfTiledMisc.cpp +@@ -301,11 +301,11 @@ calculateNumTiles (int *numTiles, + { + for (int i = 0; i < numLevels; i++) + { +- int l = levelSize (min, max, i, rmode); +- if (l >= std::numeric_limits::max() - size + 1) ++ int l = levelSize (min, max, i, rmode); ++ if (l > std::numeric_limits::max() - size + 1) + throw IEX_NAMESPACE::ArgExc ("Invalid size."); + +- numTiles[i] = (l + size - 1) / size; ++ numTiles[i] = (l + size - 1) / size; + } + } + diff --git a/CVE-2021-3475.patch b/CVE-2021-3475.patch new file mode 100644 index 0000000..23132a4 --- /dev/null +++ b/CVE-2021-3475.patch @@ -0,0 +1,35 @@ +From 2a18ed424a854598c2a20b5dd7e782b436a1e753 Mon Sep 17 00:00:00 2001 +From: Cary Phillips +Date: Sun, 30 Aug 2020 16:15:10 -0700 +Subject: [PATCH] Avoid overflow in calculateNumTiles when size=MAX_INT +(#825) + +* Avoid overflow in calculateNumTiles when size=MAX_INT + +Signed-off-by: Cary Phillips + +* Compute level size with 64 bits to avoid overflow + +Signed-off-by: Cary Phillips +--- + IlmImf/ImfTiledMisc.cpp | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/IlmImf/ImfTiledMisc.cpp +b/IlmImf/ImfTiledMisc.cpp +index c9e8731f1..b8e195fd8 100644 +--- a/IlmImf/ImfTiledMisc.cpp ++++ b/IlmImf/ImfTiledMisc.cpp +@@ -301,10 +301,8 @@ calculateNumTiles (int *numTiles, + { + for (int i = 0; i < numLevels; i++) + { +- int l = levelSize (min, max, i, rmode); +- if (l > std::numeric_limits::max() - size + 1) +- throw IEX_NAMESPACE::ArgExc ("Invalid size."); +- ++ // use 64 bits to avoid int overflow if size is large. ++ Int64 l = levelSize (min, max, i, rmode); + numTiles[i] = (l + size - 1) / size; + } + } diff --git a/CVE-2021-3476.patch b/CVE-2021-3476.patch new file mode 100644 index 0000000..8145b4c --- /dev/null +++ b/CVE-2021-3476.patch @@ -0,0 +1,70 @@ +From eec0dba242bedd2778c973ae4af112107b33d9c9 Mon Sep 17 00:00:00 2001 +From: peterhillman +Date: Wed, 7 Oct 2020 09:47:48 +1300 +Subject: [PATCH] fix undefined behavior: ignore unused bits in B44 mode + detection (#832) + +Signed-off-by: Peter Hillman +--- + IlmImf/ImfB44Compressor.cpp | 37 ++++++++++++++++------------- + 1 file changed, 20 insertions(+), 17 deletions(-) + +diff --git a/IlmImf/ImfB44Compressor.cpp b/IlmImf/ImfB44Compressor.cpp +index 3b18ba855..0725659db 100644 +--- a/IlmImf/ImfB44Compressor.cpp ++++ b/IlmImf/ImfB44Compressor.cpp +@@ -381,26 +381,26 @@ unpack14 (const unsigned char b[14], unsigned short s[16]) + s[ 0] = (b[0] << 8) | b[1]; + + unsigned short shift = (b[ 2] >> 2); +- unsigned short bias = (0x20 << shift); ++ unsigned short bias = (0x20u << shift); + +- s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3f) << shift) - bias; +- s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3f) << shift) - bias; +- s[12] = s[ 8] + ((b[ 4] & 0x3f) << shift) - bias; ++ s[ 4] = s[ 0] + ((((b[ 2] << 4) | (b[ 3] >> 4)) & 0x3fu) << shift) - bias; ++ s[ 8] = s[ 4] + ((((b[ 3] << 2) | (b[ 4] >> 6)) & 0x3fu) << shift) - bias; ++ s[12] = s[ 8] + ((b[ 4] & 0x3fu) << shift) - bias; + +- s[ 1] = s[ 0] + ((b[ 5] >> 2) << shift) - bias; +- s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3f) << shift) - bias; +- s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3f) << shift) - bias; +- s[13] = s[12] + ((b[ 7] & 0x3f) << shift) - bias; ++ s[ 1] = s[ 0] + ((unsigned int) (b[ 5] >> 2) << shift) - bias; ++ s[ 5] = s[ 4] + ((((b[ 5] << 4) | (b[ 6] >> 4)) & 0x3fu) << shift) - bias; ++ s[ 9] = s[ 8] + ((((b[ 6] << 2) | (b[ 7] >> 6)) & 0x3fu) << shift) - bias; ++ s[13] = s[12] + ((b[ 7] & 0x3fu) << shift) - bias; + +- s[ 2] = s[ 1] + ((b[ 8] >> 2) << shift) - bias; +- s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3f) << shift) - bias; +- s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3f) << shift) - bias; +- s[14] = s[13] + ((b[10] & 0x3f) << shift) - bias; ++ s[ 2] = s[ 1] + ((unsigned int)(b[ 8] >> 2) << shift) - bias; ++ s[ 6] = s[ 5] + ((((b[ 8] << 4) | (b[ 9] >> 4)) & 0x3fu) << shift) - bias; ++ s[10] = s[ 9] + ((((b[ 9] << 2) | (b[10] >> 6)) & 0x3fu) << shift) - bias; ++ s[14] = s[13] + ((b[10] & 0x3fu) << shift) - bias; + +- s[ 3] = s[ 2] + ((b[11] >> 2) << shift) - bias; +- s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3f) << shift) - bias; +- s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3f) << shift) - bias; +- s[15] = s[14] + ((b[13] & 0x3f) << shift) - bias; ++ s[ 3] = s[ 2] + ((unsigned int)(b[11] >> 2) << shift) - bias; ++ s[ 7] = s[ 6] + ((((b[11] << 4) | (b[12] >> 4)) & 0x3fu) << shift) - bias; ++ s[11] = s[10] + ((((b[12] << 2) | (b[13] >> 6)) & 0x3fu) << shift) - bias; ++ s[15] = s[14] + ((b[13] & 0x3fu) << shift) - bias; + + for (int i = 0; i < 16; ++i) + { +@@ -951,7 +951,10 @@ B44Compressor::uncompress (const char *inPtr, + if (inSize < 3) + notEnoughData(); + +- if (((const unsigned char *)inPtr)[2] == 0xfc) ++ // ++ // If shift exponent is 63, call unpack14 (ignoring unused bits) ++ // ++ if (((const unsigned char *)inPtr)[2] >= (13<<2) ) + { + unpack3 ((const unsigned char *)inPtr, s); + inPtr += 3; diff --git a/CVE-2021-3477.patch b/CVE-2021-3477.patch new file mode 100644 index 0000000..15ed659 --- /dev/null +++ b/CVE-2021-3477.patch @@ -0,0 +1,25 @@ +From 467be80b75642efbbe6bdace558079f68c16acb1 Mon Sep 17 00:00:00 2001 +From: peterhillman +Date: Tue, 10 Nov 2020 08:35:59 +1300 +Subject: [PATCH] Fix overflow computing deeptile sample table size (#861) + +Signed-off-by: Peter Hillman +--- + IlmImf/ImfDeepTiledInputFile.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/IlmImf/ImfDeepTiledInputFile.cpp b/IlmImf/ImfDeepTiledInputFile.cpp +index 0f893481b..f5abe9c6a 100644 +--- a/IlmImf/ImfDeepTiledInputFile.cpp ++++ b/IlmImf/ImfDeepTiledInputFile.cpp +@@ -1034,8 +1034,8 @@ DeepTiledInputFile::initialize () + for (size_t i = 0; i < _data->tileBuffers.size(); i++) + _data->tileBuffers[i] = new TileBuffer (); + +- _data->maxSampleCountTableSize = _data->tileDesc.ySize * +- _data->tileDesc.xSize * ++ _data->maxSampleCountTableSize = static_cast(_data->tileDesc.ySize) * ++ static_cast(_data->tileDesc.xSize) * + sizeof(int); + + _data->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize); diff --git a/CVE-2021-3478.patch b/CVE-2021-3478.patch new file mode 100644 index 0000000..1a09a4e --- /dev/null +++ b/CVE-2021-3478.patch @@ -0,0 +1,35 @@ +From bc88cdb6c97fbf5bc5d11ad8ca55306da931283a Mon Sep 17 00:00:00 2001 +From: peterhillman +Date: Fri, 20 Nov 2020 08:30:08 +1300 +Subject: [PATCH] sanity check ScanlineInput bytesPerLine instead of lineOffset + size (#863) + +Signed-off-by: Peter Hillman + +Co-authored-by: Cary Phillips +--- + IlmImf/ImfScanLineInputFile.cpp | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/IlmImf/ImfScanLineInputFile.cpp b/IlmImf/ImfScanLineInputFile.cpp +index 649fc304b..54caec01d 100644 +--- a/IlmImf/ImfScanLineInputFile.cpp ++++ b/IlmImf/ImfScanLineInputFile.cpp +@@ -1135,14 +1135,14 @@ void ScanLineInputFile::initialize(const Header& header) + _data->linesInBuffer) / _data->linesInBuffer; + + // +- // avoid allocating excessive memory due to large lineOffsets table size. ++ // avoid allocating excessive memory due to large lineOffsets and bytesPerLine table sizes. + // If the chunktablesize claims to be large, +- // check the file is big enough to contain the table before allocating memory ++ // check the file is big enough to contain the lineOffsets table before allocating memory + // in the bytesPerLineTable and the lineOffsets table. + // Attempt to read the last entry in the table. Either the seekg() or the read() + // call will throw an exception if the file is too small to contain the table + // +- if (lineOffsetSize > gLargeChunkTableSize) ++ if (lineOffsetSize * _data->linesInBuffer > gLargeChunkTableSize) + { + Int64 pos = _streamData->is->tellg(); + _streamData->is->seekg(pos + (lineOffsetSize-1)*sizeof(Int64)); diff --git a/CVE-2021-3479-pre0.patch b/CVE-2021-3479-pre0.patch new file mode 100644 index 0000000..5bb9c78 --- /dev/null +++ b/CVE-2021-3479-pre0.patch @@ -0,0 +1,174 @@ +From 969907789e687469a9ee5c003656f761e77fe15d Mon Sep 17 00:00:00 2001 +From: Peter Hillman +Date: Fri, 26 Jul 2019 18:25:44 +1200 +Subject: [PATCH] Fix #452: read floats with 32 bit alignment + +--- + IlmImf/ImfMisc.cpp | 18 +++++++- + .../testOptimizedInterleavePatterns.cpp | 46 +++++++++++++++++-- + 2 files changed, 59 insertions(+), 5 deletions(-) + +diff --git a/IlmImf/ImfMisc.cpp b/IlmImf/ImfMisc.cpp +index 4622c4170..277554320 100644 +--- a/IlmImf/ImfMisc.cpp ++++ b/IlmImf/ImfMisc.cpp +@@ -1381,6 +1381,20 @@ skipChannel (const char *& readPtr, + } + + ++namespace ++{ ++// ++// helper function to realign floats ++// for architectures that require 32-bit alignment for float reading ++// ++ ++struct FBytes { uint8_t b[4]; }; ++union bytesOrFloat { ++ FBytes b; ++ float f; ++} ; ++} ++ + void + convertInPlace (char *& writePtr, + const char *& readPtr, +@@ -1411,7 +1425,9 @@ convertInPlace (char *& writePtr, + + for (size_t j = 0; j < numPixels; ++j) + { +- Xdr::write (writePtr, *(const float *) readPtr); ++ union bytesOrFloat tmp; ++ tmp.b = * reinterpret_cast( readPtr ); ++ Xdr::write (writePtr, tmp.f); + readPtr += sizeof(float); + } + break; +diff --git a/IlmImfTest/testOptimizedInterleavePatterns.cpp b/IlmImfTest/testOptimizedInterleavePatterns.cpp +index 1ed74d2e7..f24c09cab 100644 +--- a/IlmImfTest/testOptimizedInterleavePatterns.cpp ++++ b/IlmImfTest/testOptimizedInterleavePatterns.cpp +@@ -171,6 +171,14 @@ Schema Schemes[] = + {NULL,NULL,NULL,0,NULL,NULL} + }; + ++template inline T alignToFour(T input) ++{ ++ while( (intptr_t(input)&3) !=0 ) ++ { ++ input++; ++ } ++ return input; ++} + + + bool compare(const FrameBuffer& asRead, +@@ -192,6 +200,7 @@ bool compare(const FrameBuffer& asRead, + switch (i.slice().type) + { + case IMF::FLOAT : ++ assert(alignToFour(ptr)==ptr); + readHalf = half(*(float*) ptr); + break; + case IMF::HALF : +@@ -213,6 +222,7 @@ bool compare(const FrameBuffer& asRead, + switch (p.slice().type) + { + case IMF::FLOAT : ++ assert(alignToFour(ptr)==ptr); + writtenHalf = half(*(float*) ptr); + break; + case IMF::HALF : +@@ -250,6 +260,8 @@ bool compare(const FrameBuffer& asRead, + return true; + } + ++ ++ + // + // allocate readingBuffer or writingBuffer, setting up a framebuffer to point to the right thing + // +@@ -272,7 +284,7 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + // + int activechans = 0; + int bytes_per_pixel =0; +- ++ bool has32BitValue = false; + while (channels[activechans]!=NULL) + { + if (pt==NULL) +@@ -284,7 +296,15 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + switch (pt[activechans]) + { + case IMF::HALF : bytes_per_pixel+=2;break; +- case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break; ++ case IMF::FLOAT : case IMF::UINT : ++ // some architectures (e.g arm7 cannot write 32 bit values ++ // to addresses which aren't aligned to 32 bit addresses) ++ // so bump to next multiple of four ++ bytes_per_pixel = alignToFour(bytes_per_pixel); ++ bytes_per_pixel+=4; ++ has32BitValue = true; ++ break; ++ + default : + cout << "Unexpected PixelType?\n"; + exit(1); +@@ -306,7 +326,11 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + switch (pt[passivechans+activechans]) + { + case IMF::HALF : bytes_per_pixel+=2;break; +- case IMF::FLOAT : case IMF::UINT : bytes_per_pixel+=4;break; ++ case IMF::FLOAT : case IMF::UINT : ++ bytes_per_pixel = alignToFour(bytes_per_pixel); ++ bytes_per_pixel+=4; ++ has32BitValue = true; ++ break; + default : + cout << "Unexpected PixelType?\n"; + exit(1); +@@ -314,6 +338,11 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + } + passivechans++; + } ++ ++ if(has32BitValue) ++ { ++ bytes_per_pixel = alignToFour(bytes_per_pixel); ++ } + + int chans = activechans+passivechans; + +@@ -350,7 +379,9 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + } + else + { ++ write_ptr = alignToFour(write_ptr); + *(float*)write_ptr = float(v); ++ + write_ptr+=4; + } + chan++; +@@ -395,7 +426,13 @@ setupBuffer (const Header& hdr, // header to grab datawindow from + offset = (writing ? &writingBuffer[0] : + &readingBuffer[0]) + bank*bytes_per_bank_row - first_pixel_index; + } +- ++ ++ ++ if(type==FLOAT || type==UINT) ++ { ++ offset = alignToFour(offset); ++ } ++ + if (i +Date: Tue, 6 Apr 2021 15:16:42 +0800 +Subject: [PATCH] lighter weight reading of Luma-only images via RgbaInputFile + (#827) + +Signed-off-by: Peter Hillman + +Co-authored-by: Cary Phillips +--- + IlmImf/ImfRgbaFile.cpp | 89 ++++++++++++++++++++++++++++++------------ + IlmImfTest/testYca.cpp | 1 + + 2 files changed, 64 insertions(+), 26 deletions(-) + +diff --git a/IlmImf/ImfRgbaFile.cpp b/IlmImf/ImfRgbaFile.cpp +index c2b604a..2ebfbed 100644 +--- a/IlmImf/ImfRgbaFile.cpp ++++ b/IlmImf/ImfRgbaFile.cpp +@@ -1169,7 +1169,7 @@ RgbaInputFile::RgbaInputFile (const char name[], int numThreads): + { + RgbaChannels rgbaChannels = channels(); + +- if (rgbaChannels & (WRITE_Y | WRITE_C)) ++ if (rgbaChannels & WRITE_C) + _fromYca = new FromYca (*_inputFile, rgbaChannels); + } + +@@ -1181,7 +1181,7 @@ RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, int n + { + RgbaChannels rgbaChannels = channels(); + +- if (rgbaChannels & (WRITE_Y | WRITE_C)) ++ if (rgbaChannels & WRITE_C) + _fromYca = new FromYca (*_inputFile, rgbaChannels); + } + +@@ -1196,7 +1196,7 @@ RgbaInputFile::RgbaInputFile (const char name[], + { + RgbaChannels rgbaChannels = channels(); + +- if (rgbaChannels & (WRITE_Y | WRITE_C)) ++ if (rgbaChannels & WRITE_C) + _fromYca = new FromYca (*_inputFile, rgbaChannels); + } + +@@ -1211,7 +1211,7 @@ RgbaInputFile::RgbaInputFile (OPENEXR_IMF_INTERNAL_NAMESPACE::IStream &is, + { + RgbaChannels rgbaChannels = channels(); + +- if (rgbaChannels & (WRITE_Y | WRITE_C)) ++ if (rgbaChannels & WRITE_C) + _fromYca = new FromYca (*_inputFile, rgbaChannels); + } + +@@ -1238,27 +1238,42 @@ RgbaInputFile::setFrameBuffer (Rgba *base, size_t xStride, size_t yStride) + + FrameBuffer fb; + +- fb.insert (_channelNamePrefix + "R", +- Slice (HALF, +- (char *) &base[0].r, +- xs, ys, +- 1, 1, // xSampling, ySampling +- 0.0)); // fillValue +- +- fb.insert (_channelNamePrefix + "G", +- Slice (HALF, +- (char *) &base[0].g, +- xs, ys, +- 1, 1, // xSampling, ySampling +- 0.0)); // fillValue +- +- fb.insert (_channelNamePrefix + "B", +- Slice (HALF, +- (char *) &base[0].b, +- xs, ys, +- 1, 1, // xSampling, ySampling +- 0.0)); // fillValue +- ++ if( channels() & WRITE_Y ) ++ { ++ fb.insert (_channelNamePrefix + "Y", ++ Slice (HALF, ++ (char *) &base[0].r, ++ xs, ys, ++ 1, 1, // xSampling, ySampling ++ 0.0)); // fillValue ++ } ++ else ++ { ++ ++ ++ fb.insert (_channelNamePrefix + "R", ++ Slice (HALF, ++ (char *) &base[0].r, ++ xs, ys, ++ 1, 1, // xSampling, ySampling ++ 0.0)); // fillValue ++ ++ ++ ++ fb.insert (_channelNamePrefix + "G", ++ Slice (HALF, ++ (char *) &base[0].g, ++ xs, ys, ++ 1, 1, // xSampling, ySampling ++ 0.0)); // fillValue ++ ++ fb.insert (_channelNamePrefix + "B", ++ Slice (HALF, ++ (char *) &base[0].b, ++ xs, ys, ++ 1, 1, // xSampling, ySampling ++ 0.0)); // fillValue ++ } + fb.insert (_channelNamePrefix + "A", + Slice (HALF, + (char *) &base[0].a, +@@ -1281,7 +1296,7 @@ RgbaInputFile::setLayerName (const string &layerName) + + RgbaChannels rgbaChannels = channels(); + +- if (rgbaChannels & (WRITE_Y | WRITE_C)) ++ if (rgbaChannels & WRITE_C) + _fromYca = new FromYca (*_inputFile, rgbaChannels); + + FrameBuffer fb; +@@ -1300,6 +1315,28 @@ RgbaInputFile::readPixels (int scanLine1, int scanLine2) + else + { + _inputFile->readPixels (scanLine1, scanLine2); ++ ++ if (channels() & WRITE_Y) ++ { ++ // ++ // Luma channel has been written into red channel ++ // Duplicate into green and blue channel to create gray image ++ // ++ const Slice* s = _inputFile->frameBuffer().findSlice(_channelNamePrefix + "Y"); ++ Box2i dataWindow = _inputFile->header().dataWindow(); ++ ++ for( int scanLine = scanLine1 ; scanLine <= scanLine2 ; scanLine++ ) ++ { ++ char* rowBase = s->base + scanLine*s->yStride; ++ for(int x = dataWindow.min.x ; x <= dataWindow.max.x ; ++x ) ++ { ++ Rgba* pixel = reinterpret_cast(rowBase+x*s->xStride); ++ pixel->g = pixel->r; ++ pixel->b = pixel->r; ++ } ++ ++ } ++ } + } + } + +diff --git a/IlmImfTest/testYca.cpp b/IlmImfTest/testYca.cpp +index 0d3459e..3007552 100644 +--- a/IlmImfTest/testYca.cpp ++++ b/IlmImfTest/testYca.cpp +@@ -187,6 +187,7 @@ writeReadYca (const char fileName[], + else + { + assert (p1.g == p2.g); ++ assert (p1.b == p2.b); + } + + if (channels & WRITE_A) +-- +2.23.0 + diff --git a/CVE-2021-3479-pre2.patch b/CVE-2021-3479-pre2.patch new file mode 100644 index 0000000..eb4f0f4 --- /dev/null +++ b/CVE-2021-3479-pre2.patch @@ -0,0 +1,680 @@ +From 3c05eacda70e3ac00ca45287aa4c8de7262a0673 Mon Sep 17 00:00:00 2001 +From: peterhillman +Date: Tue, 8 Sep 2020 10:03:03 +1200 +Subject: [PATCH] Address issues reported by Undefined Behavior Sanitizer + running IlmImfTest (#828) + +* add join() to IlmThread for avoiding use-after-free race condition + +Signed-off-by: Peter Hillman + +* Use intptr_t in pointer math with negatives (pointer overflow behavior undefined) + +Signed-off-by: Peter Hillman + +* fix undefined behavior reading non-aligned 32/64 bit ints + +Signed-off-by: Peter Hillman + +* fix undefined behavior warnings in IlmImfTest + +Signed-off-by: Peter Hillman + +* cleaner pointer casting/typo fix + +Signed-off-by: Peter Hillman +--- + IlmImf/ImfCompositeDeepScanLine.cpp | 9 +++--- + IlmImf/ImfDeepScanLineInputFile.cpp | 28 +++++++++++++---- + IlmImf/ImfDeepScanLineOutputFile.cpp | 30 +++++++++++++++++-- + IlmImf/ImfFrameBuffer.cpp | 4 +-- + IlmImf/ImfInputFile.cpp | 13 ++++---- + IlmImf/ImfMisc.cpp | 9 ++++-- + IlmImf/ImfOutputFile.cpp | 15 ++++++---- + IlmImf/ImfRgbaFile.cpp | 24 ++++++++++----- + IlmImf/ImfScanLineInputFile.cpp | 19 +++++++----- + IlmImf/ImfTiledInputFile.cpp | 5 ++-- + IlmImf/ImfTiledOutputFile.cpp | 5 ++-- + IlmImf/ImfTiledRgbaFile.cpp | 13 ++++++-- + .../IlmImfTest/testCompositeDeepScanLine.cpp | 3 +- + IlmImfTest/testDwaCompressorSimd.cpp | 3 +- + IlmImfTest/testMultiPartApi.cpp | 15 ++-------- + IlmImfTest/testMultiPartThreading.cpp | 16 ++-------- + .../testOptimizedInterleavePatterns.cpp | 12 ++++++-- + IlmImfTest/testPreviewImage.cpp | 2 +- + IlmImfTest/testSharedFrameBuffer.cpp | 23 ++++++++------ + 25 files changed, 207 insertions(+), 93 deletions(-) + +diff --git a/IlmImf/ImfCompositeDeepScanLine.cpp b/IlmImf/ImfCompositeDeepScanLine.cpp +index fac7fc432..1572c069e 100644 +--- a/IlmImf/ImfCompositeDeepScanLine.cpp ++++ b/IlmImf/ImfCompositeDeepScanLine.cpp +@@ -323,7 +323,6 @@ class LineCompositeTask : public Task + + }; + +- + void + composite_line(int y, + int start, +@@ -386,16 +385,18 @@ composite_line(int y, + { + + float value = output_pixel[ _Data->_bufferMap[channel_number] ]; // value to write +- ++ intptr_t base = reinterpret_cast(it.slice().base); + + // cast to half float if necessary + if(it.slice().type==OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT) + { +- * (float *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = value; ++ float* ptr = reinterpret_cast(base + y*it.slice().yStride + x*it.slice().xStride); ++ *ptr = value; + } + else if(it.slice().type==HALF) + { +- * (half *)(it.slice().base + y*it.slice().yStride + x*it.slice().xStride) = half(value); ++ half* ptr = reinterpret_cast(base + y*it.slice().yStride + x*it.slice().xStride); ++ *ptr = half(value); + } + + channel_number++; +diff --git a/IlmImf/ImfDeepScanLineInputFile.cpp b/IlmImf/ImfDeepScanLineInputFile.cpp +index 0844d2349..c39bd225a 100644 +--- a/IlmImf/ImfDeepScanLineInputFile.cpp ++++ b/IlmImf/ImfDeepScanLineInputFile.cpp +@@ -1425,6 +1425,20 @@ DeepScanLineInputFile::readPixels (int scanLine) + } + + ++namespace ++{ ++struct I64Bytes ++{ ++ uint8_t b[8]; ++}; ++ ++ ++union bytesOrInt64 ++{ ++ I64Bytes b; ++ Int64 i; ++}; ++} + void + DeepScanLineInputFile::rawPixelData (int firstScanLine, + char *pixelData, +@@ -1507,12 +1521,16 @@ DeepScanLineInputFile::rawPixelData (int firstScanLine, + + // copy the values we have read into the output block + *(int *) pixelData = yInFile; +- *(Int64 *) (pixelData+4) =sampleCountTableSize; +- *(Int64 *) (pixelData+12) = packedDataSize; +- ++ bytesOrInt64 tmp; ++ tmp.i=sampleCountTableSize; ++ memcpy(pixelData+4,&tmp.b,8); ++ tmp.i = packedDataSize; ++ memcpy(pixelData+12,&tmp.b,8); ++ + // didn't read the unpackedsize - do that now +- Xdr::read (*_data->_streamData->is, *(Int64 *) (pixelData+20)); +- ++ Xdr::read (*_data->_streamData->is,tmp.i); ++ memcpy(pixelData+20,&tmp.b,8); ++ + // read the actual data + _data->_streamData->is->read(pixelData+28, sampleCountTableSize+packedDataSize); + +diff --git a/IlmImf/ImfDeepScanLineOutputFile.cpp b/IlmImf/ImfDeepScanLineOutputFile.cpp +index 6e302440b..d455df9e9 100644 +--- a/IlmImf/ImfDeepScanLineOutputFile.cpp ++++ b/IlmImf/ImfDeepScanLineOutputFile.cpp +@@ -1411,6 +1411,23 @@ DeepScanLineOutputFile::copyPixels (DeepScanLineInputPart &in) + copyPixels(*in.file); + } + ++ ++// helper structure to read Int64 from non 8 byte aligned addresses ++namespace ++{ ++struct I64Bytes ++{ ++ uint8_t b[8]; ++}; ++ ++ ++union bytesOrInt64 ++{ ++ I64Bytes b; ++ Int64 i; ++}; ++} ++ + void + DeepScanLineOutputFile::copyPixels (DeepScanLineInputFile &in) + { +@@ -1487,9 +1504,16 @@ DeepScanLineOutputFile::copyPixels (DeepScanLineInputFile &in) + + // extract header from block to pass to writePixelData + +- Int64 packedSampleCountSize = *(Int64 *) (&data[4]); +- Int64 packedDataSize = *(Int64 *) (&data[12]); +- Int64 unpackedDataSize = *(Int64 *) (&data[20]); ++ bytesOrInt64 tmp; ++ memcpy(&tmp.b,&data[4],8); ++ Int64 packedSampleCountSize = tmp.i; ++ ++ memcpy(&tmp.b,&data[12],8); ++ Int64 packedDataSize = tmp.i; ++ ++ memcpy(&tmp.b,&data[20],8); ++ Int64 unpackedDataSize = tmp.i; ++ + const char * sampleCountTable = &data[0]+28; + const char * pixelData = sampleCountTable + packedSampleCountSize; + +diff --git a/IlmImf/ImfFrameBuffer.cpp b/IlmImf/ImfFrameBuffer.cpp +index a11ab4e63..a6b26b2a4 100644 +--- a/IlmImf/ImfFrameBuffer.cpp ++++ b/IlmImf/ImfFrameBuffer.cpp +@@ -89,7 +89,7 @@ Slice::Make ( + bool xTileCoords, + bool yTileCoords) + { +- char* base = reinterpret_cast (const_cast (ptr)); ++ intptr_t base = reinterpret_cast (const_cast (ptr)); + if (xStride == 0) + { + switch (type) +@@ -117,7 +117,7 @@ Slice::Make ( + + return Slice ( + type, +- base - offx - offy, ++ reinterpret_cast(base - offx - offy), + xStride, + yStride, + xSampling, +diff --git a/IlmImf/ImfInputFile.cpp b/IlmImf/ImfInputFile.cpp +index 8695c65bf..6bcb451ec 100644 +--- a/IlmImf/ImfInputFile.cpp ++++ b/IlmImf/ImfInputFile.cpp +@@ -308,6 +308,10 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) + while (modp (yStart, toSlice.ySampling) != 0) + ++yStart; + ++ ++ intptr_t fromBase = reinterpret_cast(fromSlice.base); ++ intptr_t toBase = reinterpret_cast(toSlice.base); ++ + for (int y = yStart; + y <= maxYThisRow; + y += toSlice.ySampling) +@@ -316,14 +320,13 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) + // Set the pointers to the start of the y scanline in + // this row of tiles + // +- +- fromPtr = fromSlice.base + ++ fromPtr = reinterpret_cast (fromBase + + (y - tileRange.min.y) * fromSlice.yStride + +- xStart * fromSlice.xStride; ++ xStart * fromSlice.xStride); + +- toPtr = toSlice.base + ++ toPtr = reinterpret_cast (toBase + + divp (y, toSlice.ySampling) * toSlice.yStride + +- divp (xStart, toSlice.xSampling) * toSlice.xStride; ++ divp (xStart, toSlice.xSampling) * toSlice.xStride); + + // + // Copy all pixels for the scanline in this row of tiles +diff --git a/IlmImf/ImfMisc.cpp b/IlmImf/ImfMisc.cpp +index b397b9f98..bae4622b7 100644 +--- a/IlmImf/ImfMisc.cpp ++++ b/IlmImf/ImfMisc.cpp +@@ -1390,9 +1390,10 @@ namespace + // + + struct FBytes { uint8_t b[4]; }; +-union bytesOrFloat { ++union bytesUintOrFloat { + FBytes b; + float f; ++ unsigned int u; + } ; + } + +@@ -1408,7 +1409,9 @@ convertInPlace (char *& writePtr, + + for (size_t j = 0; j < numPixels; ++j) + { +- Xdr::write (writePtr, *(const unsigned int *) readPtr); ++ union bytesUintOrFloat tmp; ++ tmp.b = * reinterpret_cast( readPtr ); ++ Xdr::write (writePtr, tmp.u); + readPtr += sizeof(unsigned int); + } + break; +@@ -1426,7 +1429,7 @@ convertInPlace (char *& writePtr, + + for (size_t j = 0; j < numPixels; ++j) + { +- union bytesOrFloat tmp; ++ union bytesUintOrFloat tmp; + tmp.b = * reinterpret_cast( readPtr ); + Xdr::write (writePtr, tmp.f); + readPtr += sizeof(float); +diff --git a/IlmImf/ImfOutputFile.cpp b/IlmImf/ImfOutputFile.cpp +index d0e34988e..899303ea6 100644 +--- a/IlmImf/ImfOutputFile.cpp ++++ b/IlmImf/ImfOutputFile.cpp +@@ -558,13 +558,18 @@ LineBufferTask::execute () + // If necessary, convert the pixel data to Xdr format. + // Then store the pixel data in _ofd->lineBuffer. + // +- +- const char *linePtr = slice.base + +- divp (y, slice.ySampling) * ++ // slice.base may be 'negative' but ++ // pointer arithmetic is not allowed to overflow, so ++ // perform computation with the non-pointer 'intptr_t' instead ++ // ++ intptr_t base = reinterpret_cast(slice.base); ++ intptr_t linePtr = base + divp (y, slice.ySampling) * + slice.yStride; + +- const char *readPtr = linePtr + dMinX * slice.xStride; +- const char *endPtr = linePtr + dMaxX * slice.xStride; ++ const char *readPtr = reinterpret_cast(linePtr + ++ dMinX * slice.xStride); ++ const char *endPtr = reinterpret_cast(linePtr + ++ dMaxX * slice.xStride); + + copyFromFrameBuffer (writePtr, readPtr, endPtr, + slice.xStride, _ofd->format, +diff --git a/IlmImf/ImfRgbaFile.cpp b/IlmImf/ImfRgbaFile.cpp +index 68fa51cb5..9e781abeb 100644 +--- a/IlmImf/ImfRgbaFile.cpp ++++ b/IlmImf/ImfRgbaFile.cpp +@@ -369,6 +369,7 @@ RgbaOutputFile::ToYca::writePixels (int numScanLines) + "\"" << _outputFile.fileName() << "\"."); + } + ++ intptr_t base = reinterpret_cast(_fbBase); + if (_writeY && !_writeC) + { + // +@@ -385,8 +386,9 @@ RgbaOutputFile::ToYca::writePixels (int numScanLines) + + for (int j = 0; j < _width; ++j) + { +- _tmpBuf[j] = _fbBase[_fbYStride * _currentScanLine + +- _fbXStride * (j + _xMin)]; ++ _tmpBuf[j] = *reinterpret_cast(base + sizeof(Rgba)* ++ (_fbYStride * _currentScanLine + ++ _fbXStride * (j + _xMin))); + } + + // +@@ -418,10 +420,13 @@ RgbaOutputFile::ToYca::writePixels (int numScanLines) + // frame buffer into _tmpBuf. + // + ++ intptr_t base = reinterpret_cast(_fbBase); ++ + for (int j = 0; j < _width; ++j) + { +- _tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine + +- _fbXStride * (j + _xMin)]; ++ const Rgba* ptr = reinterpret_cast(base+sizeof(Rgba)* ++ (_fbYStride * _currentScanLine + _fbXStride * (j + _xMin)) ); ++ _tmpBuf[j + N2] = *ptr; + } + + // +@@ -1081,9 +1086,13 @@ RgbaInputFile::FromYca::readPixels (int scanLine) + + fixSaturation (_yw, _width, _buf2, _tmpBuf); + +- for (int i = 0; i < _width; ++i) +- _fbBase[_fbYStride * scanLine + _fbXStride * (i + _xMin)] = _tmpBuf[i]; + ++ intptr_t base = reinterpret_cast(_fbBase); ++ for (int i = 0; i < _width; ++i) ++ { ++ Rgba* ptr = reinterpret_cast(base + sizeof(Rgba)*(_fbYStride * scanLine + _fbXStride * (i + _xMin))); ++ *ptr = _tmpBuf[i]; ++ } + _currentScanLine = scanLine; + } + +@@ -1335,10 +1344,11 @@ RgbaInputFile::readPixels (int scanLine1, int scanLine2) + // + const Slice* s = _inputFile->frameBuffer().findSlice(_channelNamePrefix + "Y"); + Box2i dataWindow = _inputFile->header().dataWindow(); ++ intptr_t base = reinterpret_cast(s->base); + + for( int scanLine = scanLine1 ; scanLine <= scanLine2 ; scanLine++ ) + { +- char* rowBase = s->base + scanLine*s->yStride; ++ intptr_t rowBase = base + scanLine*s->yStride; + for(int x = dataWindow.min.x ; x <= dataWindow.max.x ; ++x ) + { + Rgba* pixel = reinterpret_cast(rowBase+x*s->xStride); +diff --git a/IlmImf/ImfScanLineInputFile.cpp b/IlmImf/ImfScanLineInputFile.cpp +index b020cb9bb..a0e9a3678 100644 +--- a/IlmImf/ImfScanLineInputFile.cpp ++++ b/IlmImf/ImfScanLineInputFile.cpp +@@ -636,12 +636,14 @@ LineBufferTask::execute () + // The frame buffer contains a slice for this channel. + // + +- char *linePtr = slice.base + ++ intptr_t base = reinterpret_cast(slice.base); ++ ++ intptr_t linePtr = base + + intptr_t( divp (y, slice.ySampling) ) * + intptr_t( slice.yStride ); + +- char *writePtr = linePtr + intptr_t( dMinX ) * intptr_t( slice.xStride ); +- char *endPtr = linePtr + intptr_t( dMaxX ) * intptr_t( slice.xStride ); ++ char *writePtr = reinterpret_cast (linePtr + intptr_t( dMinX ) * intptr_t( slice.xStride )); ++ char *endPtr = reinterpret_cast (linePtr + intptr_t( dMaxX ) * intptr_t( slice.xStride )); + + copyIntoFrameBuffer (readPtr, writePtr, endPtr, + slice.xStride, slice.fill, +@@ -794,20 +796,21 @@ void LineBufferTaskIIF::getWritePointer + outWritePointerRight = 0; + } + +- const char* linePtr1 = firstSlice.base + ++ intptr_t base = reinterpret_cast(firstSlice.base); ++ ++ intptr_t linePtr1 = (base + + divp (y, firstSlice.ySampling) * +- firstSlice.yStride; ++ firstSlice.yStride); + + int dMinX1 = divp (_ifd->minX, firstSlice.xSampling); + int dMaxX1 = divp (_ifd->maxX, firstSlice.xSampling); + + // Construct the writePtr so that we start writing at + // linePtr + Min offset in the line. +- outWritePointerRight = (unsigned short*)(linePtr1 + ++ outWritePointerRight = reinterpret_cast(linePtr1 + + dMinX1 * firstSlice.xStride ); + +- size_t bytesToCopy = ((linePtr1 + dMaxX1 * firstSlice.xStride ) - +- (linePtr1 + dMinX1 * firstSlice.xStride )) + 2; ++ size_t bytesToCopy = ((dMaxX1 * firstSlice.xStride ) - (dMinX1 * firstSlice.xStride )) + 2; + size_t shortsToCopy = bytesToCopy / sizeOfSingleValue; + size_t pixelsToCopy = (shortsToCopy / nbSlicesInBank ) + 1; + +diff --git a/IlmImf/ImfTiledInputFile.cpp b/IlmImf/ImfTiledInputFile.cpp +index 3e7fda333..95edba917 100644 +--- a/IlmImf/ImfTiledInputFile.cpp ++++ b/IlmImf/ImfTiledInputFile.cpp +@@ -609,10 +609,11 @@ TileBufferTask::execute () + // The frame buffer contains a slice for this channel. + // + +- char *writePtr = slice.base + ++ intptr_t base = reinterpret_cast(slice.base); ++ char *writePtr = reinterpret_cast(base + + (y - yOffset) * slice.yStride + + (tileRange.min.x - xOffset) * +- slice.xStride; ++ slice.xStride); + + char *endPtr = writePtr + + (numPixelsPerScanLine - 1) * slice.xStride; +diff --git a/IlmImf/ImfTiledOutputFile.cpp b/IlmImf/ImfTiledOutputFile.cpp +index 52f7577ab..1cb164fdc 100644 +--- a/IlmImf/ImfTiledOutputFile.cpp ++++ b/IlmImf/ImfTiledOutputFile.cpp +@@ -789,10 +789,11 @@ TileBufferTask::execute () + // The frame buffer contains data for this channel. + // + +- const char *readPtr = slice.base + ++ intptr_t base = reinterpret_cast(slice.base); ++ const char *readPtr = reinterpret_cast(base + + (y - yOffset) * slice.yStride + + (tileRange.min.x - xOffset) * +- slice.xStride; ++ slice.xStride); + + const char *endPtr = readPtr + + (numPixelsPerScanLine - 1) * +diff --git a/IlmImf/ImfTiledRgbaFile.cpp b/IlmImf/ImfTiledRgbaFile.cpp +index 157aec0ab..ff90a7b3b 100644 +--- a/IlmImf/ImfTiledRgbaFile.cpp ++++ b/IlmImf/ImfTiledRgbaFile.cpp +@@ -227,11 +227,14 @@ TiledRgbaOutputFile::ToYa::writeTile (int dx, int dy, int lx, int ly) + Box2i dw = _outputFile.dataWindowForTile (dx, dy, lx, ly); + int width = dw.max.x - dw.min.x + 1; + ++ intptr_t base= reinterpret_cast(_fbBase); + for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) + { + for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) +- _buf[y1][x1] = _fbBase[x * _fbXStride + y * _fbYStride]; +- ++ { ++ Rgba* ptr = reinterpret_cast(base + sizeof(Rgba)*(x * _fbXStride + y * _fbYStride)); ++ _buf[y1][x1] = *ptr; ++ } + RGBAtoYCA (_yw, width, _writeA, _buf[y1], _buf[y1]); + } + +@@ -750,6 +753,9 @@ TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly) + + Box2i dw = _inputFile.dataWindowForTile (dx, dy, lx, ly); + int width = dw.max.x - dw.min.x + 1; ++ intptr_t base= reinterpret_cast(_fbBase); ++ ++ + + for (int y = dw.min.y, y1 = 0; y <= dw.max.y; ++y, ++y1) + { +@@ -763,7 +769,8 @@ TiledRgbaInputFile::FromYa::readTile (int dx, int dy, int lx, int ly) + + for (int x = dw.min.x, x1 = 0; x <= dw.max.x; ++x, ++x1) + { +- _fbBase[x * _fbXStride + y * _fbYStride] = _buf[y1][x1]; ++ Rgba* ptr = reinterpret_cast(base + sizeof(Rgba)*(x * _fbXStride + y * _fbYStride)); ++ *ptr = _buf[y1][x1]; + } + } + } +diff --git a/IlmImfTest/testCompositeDeepScanLine.cpp b/IlmImfTest/testCompositeDeepScanLine.cpp +index 94a7ea962..c85a07ce0 100644 +--- a/IlmImfTest/testCompositeDeepScanLine.cpp ++++ b/IlmImfTest/testCompositeDeepScanLine.cpp +@@ -341,8 +341,9 @@ class data + { + if(!dontbotherloadingdepth || (_channels[i]!="Z" && _channels[i]!="ZBack") ) + { ++ intptr_t base = reinterpret_cast(&data[i]); + framebuf.insert(_channels[i].c_str(), +- Slice(_type,(char *) (&data[i] - (dw.min.x + dw.min.y*(dw.size().x+1))*_channels.size() ), ++ Slice(_type,reinterpret_cast(base - sizeof(T)*(dw.min.x + dw.min.y*(dw.size().x+1))*_channels.size() ), + sizeof(T)*_channels.size(), + sizeof(T)*(dw.size().x+1)*_channels.size()) + ); +diff --git a/IlmImfTest/testDwaCompressorSimd.cpp b/IlmImfTest/testDwaCompressorSimd.cpp +index 0691ada6b..8c6015832 100644 +--- a/IlmImfTest/testDwaCompressorSimd.cpp ++++ b/IlmImfTest/testDwaCompressorSimd.cpp +@@ -97,8 +97,9 @@ compareBufferRelative (const SimdAlignedBuffer64f &src, + { + for (int i=0; i<64; ++i) + { ++ + double diff = fabs(src._buffer[i] - dst._buffer[i]); +- double relDiff = diff / fabs(src._buffer[i]); ++ double relDiff = src._buffer[i]==0 ? 0.0 : diff / fabs(src._buffer[i]); + + if (relDiff > relErrThresh && diff > absErrThresh) + { +diff --git a/IlmImfTest/testMultiPartApi.cpp b/IlmImfTest/testMultiPartApi.cpp +index c0bfb6882..8ce19b579 100644 +--- a/IlmImfTest/testMultiPartApi.cpp ++++ b/IlmImfTest/testMultiPartApi.cpp +@@ -391,18 +391,9 @@ generateRandomFile (int partCount, const std::string & fn) + int numYLevels = part->numYLevels(); + + // Allocating space. +- switch (pixelTypes[i]) +- { +- case 0: +- tiledUintData[i].resizeErase(numYLevels, numXLevels); +- break; +- case 1: +- tiledFloatData[i].resizeErase(numYLevels, numXLevels); +- break; +- case 2: +- tiledHalfData[i].resizeErase(numYLevels, numXLevels); +- break; +- } ++ tiledUintData[i].resizeErase(numYLevels, numXLevels); ++ tiledFloatData[i].resizeErase(numYLevels, numXLevels); ++ tiledHalfData[i].resizeErase(numYLevels, numXLevels); + + tiledFrameBuffers[i].resizeErase(numYLevels, numXLevels); + +diff --git a/IlmImfTest/testMultiPartThreading.cpp b/IlmImfTest/testMultiPartThreading.cpp +index c4e05704a..d764121a9 100644 +--- a/IlmImfTest/testMultiPartThreading.cpp ++++ b/IlmImfTest/testMultiPartThreading.cpp +@@ -560,19 +560,9 @@ generateRandomFile (int partCount, const std::string & fn) + int numXLevels = part->numXLevels(); + int numYLevels = part->numYLevels(); + +- // Allocating space. +- switch (pixelTypes[i]) +- { +- case 0: +- tiledUintData[i].resizeErase(numYLevels, numXLevels); +- break; +- case 1: +- tiledFloatData[i].resizeErase(numYLevels, numXLevels); +- break; +- case 2: +- tiledHalfData[i].resizeErase(numYLevels, numXLevels); +- break; +- } ++ tiledUintData[i].resizeErase(numYLevels, numXLevels); ++ tiledFloatData[i].resizeErase(numYLevels, numXLevels); ++ tiledHalfData[i].resizeErase(numYLevels, numXLevels); + + tiledFrameBuffers[i].resizeErase(numYLevels, numXLevels); + +diff --git a/IlmImfTest/testOptimizedInterleavePatterns.cpp b/IlmImfTest/testOptimizedInterleavePatterns.cpp +index c8ffd3671..07e64a128 100644 +--- a/IlmImfTest/testOptimizedInterleavePatterns.cpp ++++ b/IlmImfTest/testOptimizedInterleavePatterns.cpp +@@ -196,7 +196,11 @@ bool compare(const FrameBuffer& asRead, + for (int x = dataWindow.min.x; x <= dataWindow.max.x; x++) + + { +- char * ptr = (i.slice().base+i.slice().yStride*y +i.slice().xStride*x); ++ // ++ // extract value read back from file ++ // ++ intptr_t base = reinterpret_cast(i.slice().base); ++ char * ptr = reinterpret_cast(base+i.slice().yStride*intptr_t(y) +i.slice().xStride*intptr_t(x)); + half readHalf; + switch (i.slice().type) + { +@@ -218,8 +222,10 @@ bool compare(const FrameBuffer& asRead, + + if (p!=asWritten.end()) + { +- char * ptr = p.slice().base+p.slice().yStride*y + +- p.slice().xStride*x; ++ ++ intptr_t base =reinterpret_cast( p.slice().base); ++ char * ptr = reinterpret_cast(base+p.slice().yStride*intptr_t(y) + ++ p.slice().xStride*intptr_t(x)); + switch (p.slice().type) + { + case IMF::FLOAT : +diff --git a/IlmImfTest/testPreviewImage.cpp b/IlmImfTest/testPreviewImage.cpp +index 5b32c5010..4b8949822 100644 +--- a/IlmImfTest/testPreviewImage.cpp ++++ b/IlmImfTest/testPreviewImage.cpp +@@ -150,7 +150,7 @@ readWriteFiles (const char fileName1[], + file2.setFrameBuffer (pixels2 - dx - dy * w, 1, w); + file2.readPixels (dw.min.y, dw.max.y); + +- for (int i = 0; i < w * h; ++h) ++ for (size_t i = 0; i < w * h; ++i) + { + assert (pixels1[i].r == pixels2[i].r); + assert (pixels1[i].g == pixels2[i].g); +diff --git a/IlmImfTest/testSharedFrameBuffer.cpp b/IlmImfTest/testSharedFrameBuffer.cpp +index 0b2293c23..47c700ab8 100644 +--- a/IlmImfTest/testSharedFrameBuffer.cpp ++++ b/IlmImfTest/testSharedFrameBuffer.cpp +@@ -115,11 +115,7 @@ WriterThread::WriterThread (RgbaOutputFile *outfile): _outfile (outfile) + void + WriterThread::run () + { +- // +- // Signal that the thread has started +- // + +- threadSemaphore.post(); + + while (true) + { +@@ -136,6 +132,12 @@ WriterThread::run () + break; + } + } ++ ++ // ++ // Signal that the thread has finished ++ // ++ ++ threadSemaphore.post(); + } + + +@@ -146,7 +148,7 @@ class ReaderThread : public Thread + ReaderThread (RgbaInputFile *infile, int start, int step); + + virtual void run (); +- ++ + private: + + RgbaInputFile * _infile; +@@ -165,17 +167,20 @@ ReaderThread::ReaderThread (RgbaInputFile *infile, int start, int step): + void + ReaderThread::run () + { +- // +- // Signal that the thread has started +- // + +- threadSemaphore.post (); + + int num = _infile->header().dataWindow().max.y - + _infile->header().dataWindow().min.y + 1; + + for (int i = _start; i < num; i += _step) + _infile->readPixels (i); ++ ++ // ++ // Signal that the thread has finished ++ // ++ ++ threadSemaphore.post (); ++ + } + + diff --git a/CVE-2021-3479.patch b/CVE-2021-3479.patch new file mode 100644 index 0000000..b67eb06 --- /dev/null +++ b/CVE-2021-3479.patch @@ -0,0 +1,550 @@ +From d80f11f4f55100d007ae80a162bf257ec291612c Mon Sep 17 00:00:00 2001 +From: peterhillman +Date: Fri, 11 Sep 2020 11:02:20 +1200 +Subject: [PATCH] More efficient handling of filled channels reading tiles with + scanline API (#830) + +* refactor channel filling in InputFile API with tiled source + +Signed-off-by: Peter Hillman + +* handle edge-case of empty framebuffer + +Signed-off-by: Peter Hillman +--- + IlmImf/ImfInputFile.cpp | 271 ++++++++++++++++--------- + IlmImfTest/testScanLineApi.cpp | 134 +++++++++++- + 2 files changed, 310 insertions(+), 95 deletions(-) + +diff --git a/IlmImf/ImfInputFile.cpp b/IlmImf/ImfInputFile.cpp +index 6bcb451ec..2ca45a738 100644 +--- a/IlmImf/ImfInputFile.cpp ++++ b/IlmImf/ImfInputFile.cpp +@@ -278,9 +278,14 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) + // + // We don't have any valid buffered info, so we need to read in + // from the file. ++ // if no channels are being read that are present in file, cachedBuffer will be empty + // + +- ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j); ++ if (ifd->cachedBuffer->begin() != ifd->cachedBuffer->end()) ++ { ++ ifd->tFile->readTiles (0, ifd->tFile->numXTiles (0) - 1, j, j); ++ } ++ + ifd->cachedTileY = j; + } + +@@ -289,58 +294,135 @@ bufferedReadPixels (InputFile::Data* ifd, int scanLine1, int scanLine2) + // framebuffer. + // + +- for (FrameBuffer::ConstIterator k = ifd->cachedBuffer->begin(); +- k != ifd->cachedBuffer->end(); ++ for (FrameBuffer::ConstIterator k = ifd->tFileBuffer.begin(); ++ k != ifd->tFileBuffer.end(); + ++k) + { +- Slice fromSlice = k.slice(); // slice to write from +- Slice toSlice = ifd->tFileBuffer[k.name()]; // slice to write to + +- char *fromPtr, *toPtr; +- int size = pixelTypeSize (toSlice.type); + +- int xStart = levelRange.min.x; +- int yStart = minYThisRow; ++ Slice toSlice = k.slice(); // slice to read from ++ char* toPtr; + +- while (modp (xStart, toSlice.xSampling) != 0) +- ++xStart; ++ int xStart = levelRange.min.x; ++ int yStart = minYThisRow; + +- while (modp (yStart, toSlice.ySampling) != 0) +- ++yStart; ++ while (modp (xStart, toSlice.xSampling) != 0) ++ ++xStart; + ++ while (modp (yStart, toSlice.ySampling) != 0) ++ ++yStart; + +- intptr_t fromBase = reinterpret_cast(fromSlice.base); ++ FrameBuffer::ConstIterator c = ifd->cachedBuffer->find(k.name()); + intptr_t toBase = reinterpret_cast(toSlice.base); + +- for (int y = yStart; +- y <= maxYThisRow; +- y += toSlice.ySampling) ++ ++ if( c!=ifd->cachedBuffer->end()) ++ { ++ // ++ // output channel was read from source image: copy to output slice ++ // ++ Slice fromSlice = c.slice(); // slice to write to ++ intptr_t fromBase = reinterpret_cast(fromSlice.base); ++ ++ int size = pixelTypeSize (toSlice.type); ++ char* fromPtr; ++ ++ for (int y = yStart; ++ y <= maxYThisRow; ++ y += toSlice.ySampling) ++ { ++ // ++ // Set the pointers to the start of the y scanline in ++ // this row of tiles ++ // ++ ++ fromPtr = reinterpret_cast (fromBase + ++ (y - tileRange.min.y) * fromSlice.yStride + ++ xStart * fromSlice.xStride); ++ ++ toPtr = reinterpret_cast (toBase + ++ divp (y, toSlice.ySampling) * toSlice.yStride + ++ divp (xStart, toSlice.xSampling) * toSlice.xStride); ++ ++ // ++ // Copy all pixels for the scanline in this row of tiles ++ // ++ ++ for (int x = xStart; ++ x <= levelRange.max.x; ++ x += toSlice.xSampling) ++ { ++ for (int i = 0; i < size; ++i) ++ toPtr[i] = fromPtr[i]; ++ ++ fromPtr += fromSlice.xStride * toSlice.xSampling; ++ toPtr += toSlice.xStride; ++ } ++ } ++ } ++ else + { +- // +- // Set the pointers to the start of the y scanline in +- // this row of tiles +- // +- fromPtr = reinterpret_cast (fromBase + +- (y - tileRange.min.y) * fromSlice.yStride + +- xStart * fromSlice.xStride); +- +- toPtr = reinterpret_cast (toBase + +- divp (y, toSlice.ySampling) * toSlice.yStride + +- divp (xStart, toSlice.xSampling) * toSlice.xStride); +- +- // +- // Copy all pixels for the scanline in this row of tiles +- // +- +- for (int x = xStart; +- x <= levelRange.max.x; +- x += toSlice.xSampling) ++ ++ // ++ // channel wasn't present in source file: fill output slice ++ // ++ for (int y = yStart; ++ y <= maxYThisRow; ++ y += toSlice.ySampling) + { +- for (int i = 0; i < size; ++i) +- toPtr[i] = fromPtr[i]; + +- fromPtr += fromSlice.xStride * toSlice.xSampling; +- toPtr += toSlice.xStride; ++ toPtr = reinterpret_cast (toBase+ ++ divp (y, toSlice.ySampling) * toSlice.yStride + ++ divp (xStart, toSlice.xSampling) * toSlice.xStride); ++ ++ // ++ // Copy all pixels for the scanline in this row of tiles ++ // ++ ++ switch ( toSlice.type) ++ { ++ case UINT: ++ { ++ unsigned int fill = toSlice.fillValue; ++ for (int x = xStart; ++ x <= levelRange.max.x; ++ x += toSlice.xSampling) ++ { ++ * reinterpret_cast(toPtr) = fill; ++ toPtr += toSlice.xStride; ++ } ++ break; ++ } ++ case HALF : ++ { ++ half fill = toSlice.fillValue; ++ for (int x = xStart; ++ x <= levelRange.max.x; ++ x += toSlice.xSampling) ++ { ++ * reinterpret_cast(toPtr) = fill; ++ toPtr += toSlice.xStride; ++ } ++ break; ++ } ++ case FLOAT : ++ { ++ float fill = toSlice.fillValue; ++ for (int x = xStart; ++ x <= levelRange.max.x; ++ x += toSlice.xSampling) ++ { ++ * reinterpret_cast(toPtr) = fill; ++ toPtr += toSlice.xStride; ++ } ++ break; ++ } ++ case NUM_PIXELTYPES : ++ { ++ break; ++ } ++ ++ } + } + } + } +@@ -706,60 +788,67 @@ InputFile::setFrameBuffer (const FrameBuffer &frameBuffer) + { + Slice s = k.slice(); + +- switch (s.type) +- { +- case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: +- +- _data->cachedBuffer->insert +- (k.name(), +- Slice (UINT, +- (char *)(new unsigned int[tileRowSize] - +- _data->offset), +- sizeof (unsigned int), +- sizeof (unsigned int) * +- _data->tFile->levelWidth(0), +- 1, 1, +- s.fillValue, +- false, true)); +- break; +- +- case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: +- +- _data->cachedBuffer->insert +- (k.name(), +- Slice (HALF, +- (char *)(new half[tileRowSize] - +- _data->offset), +- sizeof (half), +- sizeof (half) * +- _data->tFile->levelWidth(0), +- 1, 1, +- s.fillValue, +- false, true)); +- break; +- +- case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: +- +- _data->cachedBuffer->insert +- (k.name(), +- Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, +- (char *)(new float[tileRowSize] - +- _data->offset), +- sizeof(float), +- sizeof(float) * +- _data->tFile->levelWidth(0), +- 1, 1, +- s.fillValue, +- false, true)); +- break; +- +- default: +- +- throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); +- } ++ // ++ // omit adding channels that are not listed - 'fill' channels are added later ++ // ++ if ( _data->header.channels().find(k.name()) != _data->header.channels().end() ) ++ { ++ switch (s.type) ++ { ++ case OPENEXR_IMF_INTERNAL_NAMESPACE::UINT: ++ ++ _data->cachedBuffer->insert ++ (k.name(), ++ Slice (UINT, ++ (char *)(new unsigned int[tileRowSize] - ++ _data->offset), ++ sizeof (unsigned int), ++ sizeof (unsigned int) * ++ _data->tFile->levelWidth(0), ++ 1, 1, ++ s.fillValue, ++ false, true)); ++ break; ++ ++ case OPENEXR_IMF_INTERNAL_NAMESPACE::HALF: ++ ++ _data->cachedBuffer->insert ++ (k.name(), ++ Slice (HALF, ++ (char *)(new half[tileRowSize] - ++ _data->offset), ++ sizeof (half), ++ sizeof (half) * ++ _data->tFile->levelWidth(0), ++ 1, 1, ++ s.fillValue, ++ false, true)); ++ break; ++ ++ case OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT: ++ ++ _data->cachedBuffer->insert ++ (k.name(), ++ Slice (OPENEXR_IMF_INTERNAL_NAMESPACE::FLOAT, ++ (char *)(new float[tileRowSize] - ++ _data->offset), ++ sizeof(float), ++ sizeof(float) * ++ _data->tFile->levelWidth(0), ++ 1, 1, ++ s.fillValue, ++ false, true)); ++ break; ++ ++ default: ++ ++ throw IEX_NAMESPACE::ArgExc ("Unknown pixel data type."); ++ } ++ } + } + + _data->tFile->setFrameBuffer (*_data->cachedBuffer); ++ + } + + _data->tFileBuffer = frameBuffer; +diff --git a/IlmImfTest/testScanLineApi.cpp b/IlmImfTest/testScanLineApi.cpp +index 354d2dccf..720351ea5 100644 +--- a/IlmImfTest/testScanLineApi.cpp ++++ b/IlmImfTest/testScanLineApi.cpp +@@ -93,7 +93,9 @@ writeRead (const Array2D &pi1, + int yOffset, + Compression comp, + LevelMode mode, +- LevelRoundingMode rmode) ++ LevelRoundingMode rmode, ++ bool fillChannel ++ ) + { + // + // Write the pixel data in pi1, ph1 and ph2 to a tiled +@@ -263,6 +265,16 @@ writeRead (const Array2D &pi1, + Array2D ph2 (h, w); + Array2D pf2 (h, w); + ++ Array2D fi2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D fh2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D ff2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ ++ ++ const unsigned int fillInt = 12; ++ const half fillHalf = 4.5; ++ const float fillFloat = M_PI; ++ ++ + FrameBuffer fb; + + fb.insert ("I", // name +@@ -286,6 +298,30 @@ writeRead (const Array2D &pi1, + sizeof (pf2[0][0]) * w) // yStride + ); + ++ if(fillChannel) ++ { ++ fb.insert ("FI", // name ++ Slice (IMF::UINT, // type ++ (char *) &fi2[-dwy][-dwx],// base ++ sizeof (fi2[0][0]), // xStride ++ sizeof (fi2[0][0]) * w,1,1,fillInt) // yStride ++ ); ++ ++ fb.insert ("FH", // name ++ Slice (IMF::HALF, // type ++ (char *) &fh2[-dwy][-dwx],// base ++ sizeof (fh2[0][0]), // xStride ++ sizeof (fh2[0][0]) * w,1,1,fillHalf) // yStride ++ ); ++ ++ fb.insert ("FF", // name ++ Slice (IMF::FLOAT, // type ++ (char *) &ff2[-dwy][-dwx],// base ++ sizeof (ff2[0][0]), // xStride ++ sizeof (ff2[0][0]) * w,1,1,fillFloat) // yStride ++ ); ++ } ++ + in.setFrameBuffer (fb); + for (int y = dw.min.y; y <= dw.max.y; ++y) + in.readPixels (y); +@@ -323,6 +359,13 @@ writeRead (const Array2D &pi1, + assert (pi1[y][x] == pi2[y][x]); + assert (ph1[y][x] == ph2[y][x]); + assert (pf1[y][x] == pf2[y][x]); ++ ++ if (fillChannel) ++ { ++ assert(fi2[y][x] == fillInt); ++ assert(fh2[y][x] == fillHalf); ++ assert(ff2[y][x] == fillFloat); ++ } + } + } + } +@@ -342,6 +385,10 @@ writeRead (const Array2D &pi1, + Array2D ph2 (h, w); + Array2D pf2 (h, w); + ++ Array2D fi2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D fh2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D ff2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ + FrameBuffer fb; + + fb.insert ("I", // name +@@ -364,6 +411,34 @@ writeRead (const Array2D &pi1, + sizeof (pf2[0][0]), // xStride + sizeof (pf2[0][0]) * w) // yStride + ); ++ const unsigned int fillInt = 21; ++ const half fillHalf = 42; ++ const float fillFloat = 2.8; ++ ++ if (fillChannel) ++ { ++ fb.insert ("FI", // name ++ Slice (IMF::UINT, // type ++ (char *) &fi2[-dwy][-dwx],// base ++ sizeof (fi2[0][0]), // xStride ++ sizeof (fi2[0][0]) * w,1,1,fillInt) // yStride ++ ); ++ ++ fb.insert ("FH", // name ++ Slice (IMF::HALF, // type ++ (char *) &fh2[-dwy][-dwx],// base ++ sizeof (fh2[0][0]), // xStride ++ sizeof (fh2[0][0]) * w,1,1,fillHalf) // yStride ++ ); ++ ++ fb.insert ("FF", // name ++ Slice (IMF::FLOAT, // type ++ (char *) &ff2[-dwy][-dwx],// base ++ sizeof (ff2[0][0]), // xStride ++ sizeof (ff2[0][0]) * w,1,1,fillFloat) // yStride ++ ); ++ ++ } + + in.setFrameBuffer (fb); + for (int y = dw.max.y; y >= dw.min.y; --y) +@@ -402,6 +477,12 @@ writeRead (const Array2D &pi1, + assert (pi1[y][x] == pi2[y][x]); + assert (ph1[y][x] == ph2[y][x]); + assert (pf1[y][x] == pf2[y][x]); ++ if (fillChannel) ++ { ++ assert(fi2[y][x] == fillInt); ++ assert(fh2[y][x] == fillHalf); ++ assert(ff2[y][x] == fillFloat); ++ } + } + } + } +@@ -422,6 +503,17 @@ writeRead (const Array2D &pi1, + Array2D ph2 (h, w); + Array2D pf2 (h, w); + ++ ++ Array2D fi2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D fh2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ Array2D ff2 (fillChannel ? h : 1 , fillChannel ? w : 1); ++ ++ ++ const unsigned int fillInt = 81; ++ const half fillHalf = 0.5; ++ const float fillFloat = 7.8; ++ ++ + for (int y = dw.min.y; y <= dw.max.y; ++y) + { + FrameBuffer fb; +@@ -447,6 +539,31 @@ writeRead (const Array2D &pi1, + 0) // yStride + ); + ++ if (fillChannel) ++ { ++ fb.insert ("FI", // name ++ Slice (IMF::UINT, // type ++ (char *) &fi2[y - dwy][-dwx], // base ++ sizeof (fi2[0][0]), // xStride ++ 0,1,1,fillInt) // yStride ++ ); ++ ++ fb.insert ("FH", // name ++ Slice (IMF::HALF, // type ++ (char *) &fh2[y - dwy][-dwx], // base ++ sizeof (fh2[0][0]), // xStride ++ 0,1,1,fillHalf) // yStride ++ ); ++ ++ fb.insert ("FF", // name ++ Slice (IMF::FLOAT, // type ++ (char *) &ff2[y - dwy][-dwx], // base ++ sizeof (ff2[0][0]), // xStride ++ 0,1,1,fillFloat) // yStride ++ ); ++ ++ } ++ + in.setFrameBuffer (fb); + in.readPixels (y); + } +@@ -484,7 +601,14 @@ writeRead (const Array2D &pi1, + assert (pi1[y][x] == pi2[y][x]); + assert (ph1[y][x] == ph2[y][x]); + assert (pf1[y][x] == pf2[y][x]); ++ if (fillChannel) ++ { ++ assert (fi2[y][x] == fillInt); ++ assert (fh2[y][x] == fillHalf); ++ assert (ff2[y][x] == fillFloat); ++ } + } ++ + } + } + +@@ -509,11 +633,13 @@ writeRead (const std::string &tempDir, + std::string filename = tempDir + "imf_test_scanline_api.exr"; + + writeRead (pi, ph, pf, filename.c_str(), lorder, W, H, +- xSize, ySize, dx, dy, comp, ONE_LEVEL, rmode); ++ xSize, ySize, dx, dy, comp, ONE_LEVEL, rmode , false); ++ writeRead (pi, ph, pf, filename.c_str(), lorder, W, H, ++ xSize, ySize, dx, dy, comp, MIPMAP_LEVELS, rmode , false ); + writeRead (pi, ph, pf, filename.c_str(), lorder, W, H, +- xSize, ySize, dx, dy, comp, MIPMAP_LEVELS, rmode); ++ xSize, ySize, dx, dy, comp, RIPMAP_LEVELS, rmode , false); + writeRead (pi, ph, pf, filename.c_str(), lorder, W, H, +- xSize, ySize, dx, dy, comp, RIPMAP_LEVELS, rmode); ++ xSize, ySize, dx, dy, comp, ONE_LEVEL, rmode , true); + } + + } // namespace diff --git a/OpenEXR.spec b/OpenEXR.spec index aa27403..41b1d72 100644 --- a/OpenEXR.spec +++ b/OpenEXR.spec @@ -1,7 +1,7 @@ Name: OpenEXR Summary: A high dynamic-range (HDR) image file format for use in computer imaging applications Version: 2.2.0 -Release: 18 +Release: 19 License: BSD URL: http://www.openexr.com/ Source0: http://download.savannah.nongnu.org/releases/openexr/openexr-%{version}.tar.gz @@ -9,6 +9,17 @@ Source0: http://download.savannah.nongnu.org/releases/openexr/openexr-%{v Patch0000: openexr-2.1.0-bigendian.patch Patch0001: CVE-2017-9110-9112-9116-12596.patch Patch0002: CVE-2017-9111-9113-9114-9115.patch +Patch0003: CVE-2021-3474.patch +Patch0004: CVE-2021-3477.patch +Patch0005: CVE-2021-3476.patch +Patch0006: CVE-2021-20296.patch +Patch0007: CVE-2021-3479-pre0.patch +Patch0008: CVE-2021-3479-pre1.patch +Patch0009: CVE-2021-3479-pre2.patch +Patch0010: CVE-2021-3479.patch +Patch0011: CVE-2021-3475-pre0.patch +Patch0012: CVE-2021-3475-pre1.patch +Patch0013: CVE-2021-3475.patch BuildConflicts: %{name}-devel < 2.2.0 BuildRequires: gcc-c++ ilmbase-devel >= %{version} zlib-devel pkgconfig @@ -72,6 +83,9 @@ test "$(pkg-config --modversion OpenEXR)" = "%{version}" %{_libdir}/pkgconfig/OpenEXR.pc %changelog +* Tue Apr 06 2021 wangyue - 2.2.0-19 +- fix CVE-2021-3474 CVE-2021-3477 CVE-2021-3476 CVE-2021-3475 CVE-2021-20296 CVE-2021-3479 CVE-2021-20296 + * Wed Jan 27 2021 zhanghua - 2.2.0-18 - Type:CVE - ID:NA -- Gitee