Upgrade 3.1.3

Signed-off-by: cherry530 <xuping33@huawei.com>
This commit is contained in:
cherry530 2022-02-19 10:53:08 +08:00
parent 564f685300
commit e988607372
25 changed files with 23 additions and 3521 deletions

View File

@ -1,96 +0,0 @@
From 49db4a4192482eec9c27669f75db144cf5434804 Mon Sep 17 00:00:00 2001
From: Shawn Walker-Salas <shawn.walker@oracle.com>
Date: Tue, 30 May 2017 19:07:52 -0700
Subject: [PATCH] Add additional input validation in an attempt to resolve
issue #232
---
IlmImf/ImfDwaCompressor.cpp | 7 +-
IlmImf/ImfHuf.cpp | 10 +-
IlmImf/ImfPizCompressor.cpp | 6 +
3 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/IlmImf/ImfDwaCompressor.cpp b/IlmImf/ImfDwaCompressor.cpp
index 1c1bd454e..2ef88786f 100644
--- a/IlmImf/ImfDwaCompressor.cpp
+++ b/IlmImf/ImfDwaCompressor.cpp
@@ -2377,7 +2377,12 @@ DwaCompressor::uncompress
const char *dataPtr = inPtr + NUM_SIZES_SINGLE * sizeof(Int64);
- if (inSize < headerSize + compressedSize)
+ /* Both the sum and individual sizes are checked in case of overflow. */
+ if (inSize < (headerSize + compressedSize) ||
+ inSize < unknownCompressedSize ||
+ inSize < acCompressedSize ||
+ inSize < dcCompressedSize ||
+ inSize < rleCompressedSize)
{
throw Iex::InputExc("Error uncompressing DWA data"
"(truncated file).");
diff --git a/IlmImf/ImfHuf.cpp b/IlmImf/ImfHuf.cpp
index a375d05d8..97909a5b1 100644
--- a/IlmImf/ImfHuf.cpp
+++ b/IlmImf/ImfHuf.cpp
@@ -822,7 +822,7 @@ hufEncode // return: output size (in bits)
}
-#define getCode(po, rlc, c, lc, in, out, oe) \
+#define getCode(po, rlc, c, lc, in, out, ob, oe)\
{ \
if (po == rlc) \
{ \
@@ -835,6 +835,8 @@ hufEncode // return: output size (in bits)
\
if (out + cs > oe) \
tooMuchData(); \
+ else if (out - 1 < ob) \
+ notEnoughData(); \
\
unsigned short s = out[-1]; \
\
@@ -895,7 +897,7 @@ hufDecode
//
lc -= pl.len;
- getCode (pl.lit, rlc, c, lc, in, out, oe);
+ getCode (pl.lit, rlc, c, lc, in, out, outb, oe);
}
else
{
@@ -925,7 +927,7 @@ hufDecode
//
lc -= l;
- getCode (pl.p[j], rlc, c, lc, in, out, oe);
+ getCode (pl.p[j], rlc, c, lc, in, out, outb, oe);
break;
}
}
@@ -952,7 +954,7 @@ hufDecode
if (pl.len)
{
lc -= pl.len;
- getCode (pl.lit, rlc, c, lc, in, out, oe);
+ getCode (pl.lit, rlc, c, lc, in, out, outb, oe);
}
else
{
diff --git a/IlmImf/ImfPizCompressor.cpp b/IlmImf/ImfPizCompressor.cpp
index 46c6fbace..8b3ee38c3 100644
--- a/IlmImf/ImfPizCompressor.cpp
+++ b/IlmImf/ImfPizCompressor.cpp
@@ -573,6 +573,12 @@ PizCompressor::uncompress (const char *inPtr,
int length;
Xdr::read <CharPtrIO> (inPtr, length);
+ if (length > inSize)
+ {
+ throw InputExc ("Error in header for PIZ-compressed data "
+ "(invalid array length).");
+ }
+
hufUncompress (inPtr, length, _tmpBuffer, tmpBufferEnd - _tmpBuffer);
//

View File

@ -1,436 +0,0 @@
Backports of
From ec64836c2312b13034149acab499c112bd289cd9 Mon Sep 17 00:00:00 2001
From: Kimball Thurston <kdt3rd@gmail.com>
Date: Sun, 21 Jul 2019 17:56:30 +1200
Subject: [PATCH] Refactor origin function to a Slice factory and Rgba custom
utility
From a7eec54765e9122b78a6c34bb9d5bf744631bea2 Mon Sep 17 00:00:00 2001
From: Kimball Thurston <kdt3rd@gmail.com>
Date: Mon, 1 Jul 2019 22:11:34 +1200
Subject: [PATCH] merges common fixes and move bounds check to central location
From 45f9912e6cfa0617ec2054d96d1e1e73fad4a62a Mon Sep 17 00:00:00 2001
From: Kimball Thurston <kdt3rd@gmail.com>
Date: Thu, 27 Jun 2019 23:36:09 +1200
Subject: [PATCH] Fix part of #232, issue with pointer overflows
--- openexr-2.2.1.orig/IlmImf/ImfFrameBuffer.cpp
+++ openexr-2.2.1/IlmImf/ImfFrameBuffer.cpp
@@ -74,6 +74,88 @@ Slice::Slice (PixelType t,
// empty
}
+Slice
+Slice::Make (
+ PixelType type,
+ const void* ptr,
+ const IMATH_NAMESPACE::V2i& origin,
+ int64_t w,
+ int64_t h,
+ size_t xStride,
+ size_t yStride,
+ int xSampling,
+ int ySampling,
+ double fillValue,
+ bool xTileCoords,
+ bool yTileCoords)
+{
+ char* base = reinterpret_cast<char*> (const_cast<void *> (ptr));
+ if (xStride == 0)
+ {
+ switch (type)
+ {
+ case UINT: xStride = sizeof (uint32_t); break;
+ case HALF: xStride = sizeof (uint16_t); break;
+ case FLOAT: xStride = sizeof (float); break;
+ case NUM_PIXELTYPES:
+ THROW (IEX_NAMESPACE::ArgExc, "Invalid pixel type.");
+ }
+ }
+ if (yStride == 0)
+ yStride = static_cast<size_t> (w / xSampling) * xStride;
+
+ // data window is an int, so force promote to higher type to avoid
+ // overflow for off y (degenerate size checks should be in
+ // ImfHeader::sanityCheck, but offset can be large-ish)
+ int64_t offx = (static_cast<int64_t> (origin.x) /
+ static_cast<int64_t> (xSampling));
+ offx *= static_cast<int64_t> (xStride);
+
+ int64_t offy = (static_cast<int64_t> (origin.y) /
+ static_cast<int64_t> (ySampling));
+ offy *= static_cast<int64_t> (yStride);
+
+ return Slice (
+ type,
+ base - offx - offy,
+ xStride,
+ yStride,
+ xSampling,
+ ySampling,
+ fillValue,
+ xTileCoords,
+ yTileCoords);
+}
+
+Slice
+Slice::Make (
+ PixelType type,
+ const void* ptr,
+ const IMATH_NAMESPACE::Box2i& dataWindow,
+ size_t xStride,
+ size_t yStride,
+ int xSampling,
+ int ySampling,
+ double fillValue,
+ bool xTileCoords,
+ bool yTileCoords)
+{
+ return Make (
+ type,
+ ptr,
+ dataWindow.min,
+ static_cast<int64_t> (dataWindow.max.x) -
+ static_cast<int64_t> (dataWindow.min.x) + 1,
+ static_cast<int64_t> (dataWindow.max.y) -
+ static_cast<int64_t> (dataWindow.min.y) + 1,
+ xStride,
+ yStride,
+ xSampling,
+ ySampling,
+ fillValue,
+ xTileCoords,
+ yTileCoords);
+}
void
FrameBuffer::insert (const char name[], const Slice &slice)
--- openexr-2.2.1.orig/IlmImf/ImfFrameBuffer.h
+++ openexr-2.2.1/IlmImf/ImfFrameBuffer.h
@@ -48,14 +48,15 @@
#include "ImfPixelType.h"
#include "ImfExport.h"
#include "ImfNamespace.h"
+#include "ImathBox.h"
#include <map>
#include <string>
+#include <cstdint>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
-
//-------------------------------------------------------
// Description of a single slice of the frame buffer:
//
@@ -147,6 +148,36 @@ struct IMF_EXPORT Slice
double fillValue = 0.0,
bool xTileCoords = false,
bool yTileCoords = false);
+
+ // Does the heavy lifting of computing the base pointer for a slice,
+ // avoiding overflow issues with large origin offsets
+ //
+ // if xStride == 0, assumes sizeof(pixeltype)
+ // if yStride == 0, assumes xStride * ( w / xSampling )
+ static Slice Make(PixelType type,
+ const void *ptr,
+ const IMATH_NAMESPACE::V2i &origin,
+ int64_t w,
+ int64_t h,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ int xSampling = 1,
+ int ySampling = 1,
+ double fillValue = 0.0,
+ bool xTileCoords = false,
+ bool yTileCoords = false);
+ // same as above, just computes w and h for you
+ // from a data window
+ static Slice Make(PixelType type,
+ const void *ptr,
+ const IMATH_NAMESPACE::Box2i &dataWindow,
+ size_t xStride = 0,
+ size_t yStride = 0,
+ int xSampling = 1,
+ int ySampling = 1,
+ double fillValue = 0.0,
+ bool xTileCoords = false,
+ bool yTileCoords = false);
};
--- openexr-2.2.1.orig/IlmImf/ImfHeader.cpp
+++ openexr-2.2.1/IlmImf/ImfHeader.cpp
@@ -785,30 +785,46 @@ Header::sanityCheck (bool isTiled, bool
throw IEX_NAMESPACE::ArgExc ("Invalid data window in image header.");
}
- if (maxImageWidth > 0 &&
- maxImageWidth < (dataWindow.max.x - dataWindow.min.x + 1))
+ int w = (dataWindow.max.x - dataWindow.min.x + 1);
+ if (maxImageWidth > 0 && maxImageWidth < w)
{
THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
"maximum width of " << maxImageWidth << "pixels.");
}
- if (maxImageHeight > 0 &&
- maxImageHeight < dataWindow.max.y - dataWindow.min.y + 1)
+ int h = (dataWindow.max.y - dataWindow.min.y + 1);
+ if (maxImageHeight > 0 && maxImageHeight < h)
{
- THROW (IEX_NAMESPACE::ArgExc, "The width of the data window exceeds the "
- "maximum width of " << maxImageHeight << "pixels.");
+ THROW (IEX_NAMESPACE::ArgExc, "The height of the data window exceeds the "
+ "maximum height of " << maxImageHeight << "pixels.");
+ }
+
+ // make sure to avoid simple math overflow for large offsets
+ // we know we're at a positive width because of checks above
+ long long bigW = static_cast<long long>( w );
+ long long absOffY = std::abs ( dataWindow.min.y );
+ long long absOffX = std::abs ( dataWindow.min.x );
+ long long offX = static_cast<long long>( INT_MAX ) - absOffX;
+ long long offsetCount = absOffY * bigW;
+ long long bytesLeftPerLine = static_cast<long long>( INT_MAX ) / bigW;
+ if (bytesLeftPerLine < absOffY || offX < offsetCount)
+ {
+ THROW (IEX_NAMESPACE::ArgExc, "Data window [ (" << dataWindow.min.x
+ << ", " << dataWindow.min.x << ") - (" << dataWindow.max.x
+ << ", " << dataWindow.max.x
+ << ") ] offset / size will overflow pointer calculations");
}
- // chunk table must be smaller than the maximum image area
- // (only reachable for unknown types or damaged files: will have thrown earlier
- // for regular image types)
- if( maxImageHeight>0 && maxImageWidth>0 &&
- hasChunkCount() && chunkCount()>Int64(maxImageWidth)*Int64(maxImageHeight))
- {
- THROW (IEX_NAMESPACE::ArgExc, "chunkCount exceeds maximum area of "
- << Int64(maxImageWidth)*Int64(maxImageHeight) << " pixels." );
+ // chunk table must be smaller than the maximum image area
+ // (only reachable for unknown types or damaged files: will have thrown earlier
+ // for regular image types)
+ if( maxImageHeight>0 && maxImageWidth>0 &&
+ hasChunkCount() && chunkCount()>Int64(maxImageWidth)*Int64(maxImageHeight))
+ {
+ THROW (IEX_NAMESPACE::ArgExc, "chunkCount exceeds maximum area of "
+ << Int64(maxImageWidth)*Int64(maxImageHeight) << " pixels." );
- }
+ }
//
--- openexr-2.2.1.orig/IlmImf/ImfRgbaFile.h
+++ openexr-2.2.1/IlmImf/ImfRgbaFile.h
@@ -60,6 +60,65 @@
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
+//-------------------------------------------------------
+// Utility to compute the origin-based pointer address
+//
+// With large offsets for the data window, the naive code
+// can wrap around, especially on 32-bit machines.
+// This can be used to avoid that
+//-------------------------------------------------------
+
+inline const Rgba *
+ComputeBasePointer (
+ const Rgba* ptr,
+ const IMATH_NAMESPACE::V2i& origin,
+ int64_t w,
+ size_t xStride = 1,
+ size_t yStride = 0)
+{
+ if (yStride == 0)
+ yStride = w;
+ int64_t offx = static_cast<int64_t> (origin.x);
+ offx *= xStride;
+ int64_t offy = static_cast<int64_t> (origin.y);
+ offy *= yStride;
+ return ptr - offx - offy;
+}
+
+inline const Rgba *
+ComputeBasePointer (const Rgba* ptr, const IMATH_NAMESPACE::Box2i& dataWindow)
+{
+ return ComputeBasePointer (ptr, dataWindow.min,
+ static_cast<int64_t> (dataWindow.max.x) -
+ static_cast<int64_t> (dataWindow.min.x) + 1);
+}
+
+inline Rgba*
+ComputeBasePointer (
+ Rgba* ptr,
+ const IMATH_NAMESPACE::V2i& origin,
+ int64_t w,
+ size_t xStride = 1,
+ size_t yStride = 0)
+{
+ if (yStride == 0)
+ yStride = w;
+ int64_t offx = static_cast<int64_t> (origin.x);
+ offx *= xStride;
+ int64_t offy = static_cast<int64_t> (origin.y);
+ offy *= yStride;
+ return ptr - offx - offy;
+}
+
+inline Rgba*
+ComputeBasePointer (Rgba* ptr, const IMATH_NAMESPACE::Box2i& dataWindow)
+{
+ return ComputeBasePointer (
+ ptr,
+ dataWindow.min,
+ static_cast<int64_t> (dataWindow.max.x) -
+ static_cast<int64_t> (dataWindow.min.x) + 1);
+}
//
// RGBA output file.
--- openexr-2.2.1.orig/IlmImf/ImfScanLineInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfScanLineInputFile.cpp
@@ -522,14 +522,14 @@ LineBufferTask::execute ()
if (_lineBuffer->uncompressedData == 0)
{
- int uncompressedSize = 0;
+ size_t uncompressedSize = 0;
int maxY = min (_lineBuffer->maxY, _ifd->maxY);
for (int i = _lineBuffer->minY - _ifd->minY;
i <= maxY - _ifd->minY;
++i)
{
- uncompressedSize += (int) _ifd->bytesPerLine[i];
+ uncompressedSize += _ifd->bytesPerLine[i];
}
if (_lineBuffer->compressor &&
@@ -626,11 +626,11 @@ LineBufferTask::execute ()
//
char *linePtr = slice.base +
- divp (y, slice.ySampling) *
- slice.yStride;
+ intptr_t( divp (y, slice.ySampling) ) *
+ intptr_t( slice.yStride );
- char *writePtr = linePtr + dMinX * slice.xStride;
- char *endPtr = linePtr + dMaxX * slice.xStride;
+ char *writePtr = linePtr + intptr_t( dMinX ) * intptr_t( slice.xStride );
+ char *endPtr = linePtr + intptr_t( dMaxX ) * intptr_t( slice.xStride );
copyIntoFrameBuffer (readPtr, writePtr, endPtr,
slice.xStride, slice.fill,
@@ -836,14 +836,14 @@ LineBufferTaskIIF::execute()
if (_lineBuffer->uncompressedData == 0)
{
- int uncompressedSize = 0;
+ size_t uncompressedSize = 0;
int maxY = min (_lineBuffer->maxY, _ifd->maxY);
for (int i = _lineBuffer->minY - _ifd->minY;
i <= maxY - _ifd->minY;
++i)
{
- uncompressedSize += (int) _ifd->bytesPerLine[i];
+ uncompressedSize += _ifd->bytesPerLine[i];
}
if (_lineBuffer->compressor &&
--- openexr-2.2.1.orig/exrenvmap/readInputImage.cpp
+++ openexr-2.2.1/exrenvmap/readInputImage.cpp
@@ -194,7 +194,7 @@ readSixImages (const char inFileName[],
"from the data window of other cube faces.");
}
- in.setFrameBuffer (pixels - dw.min.x - dw.min.y * w, 1, w);
+ in.setFrameBuffer (ComputeBasePointer (pixels, dw), 1, w);
in.readPixels (dw.min.y, dw.max.y);
pixels += w * h;
--- openexr-2.2.1.orig/exrmakepreview/makePreview.cpp
+++ openexr-2.2.1/exrmakepreview/makePreview.cpp
@@ -110,7 +110,7 @@ generatePreview (const char inFileName[]
int h = dw.max.y - dw.min.y + 1;
Array2D <Rgba> pixels (h, w);
- in.setFrameBuffer (&pixels[0][0] - dw.min.y * w - dw.min.x, 1, w);
+ in.setFrameBuffer (ComputeBasePointer (&pixels[0][0], dw), 1, w);
in.readPixels (dw.min.y, dw.max.y);
//
--- openexr-2.2.1.orig/exrmaketiled/Image.h
+++ openexr-2.2.1/exrmaketiled/Image.h
@@ -190,12 +190,12 @@ OPENEXR_IMF_INTERNAL_NAMESPACE::Slice
TypedImageChannel<T>::slice () const
{
const IMATH_NAMESPACE::Box2i &dw = image().dataWindow();
- int w = dw.max.x - dw.min.x + 1;
- return OPENEXR_IMF_INTERNAL_NAMESPACE::Slice (pixelType(),
- (char *) (&_pixels[0][0] - dw.min.y * w - dw.min.x),
- sizeof (T),
- w * sizeof (T));
+ return OPENEXR_IMF_INTERNAL_NAMESPACE::Slice::Make (
+ pixelType(),
+ &_pixels[0][0],
+ dw,
+ sizeof (T));
}
--- openexr-2.2.1.orig/exrmultiview/Image.h
+++ openexr-2.2.1/exrmultiview/Image.h
@@ -159,6 +159,8 @@ TypedImageChannel<T>::TypedImageChannel
_ySampling (ySampling),
_pixels (0, 0)
{
+ if ( _xSampling < 1 || _ySampling < 1 )
+ throw IEX_NAMESPACE::ArgExc ("Invalid x/y sampling values");
resize();
}
@@ -201,14 +203,14 @@ TypedImageChannel<T>::slice () const
const IMATH_NAMESPACE::Box2i &dw = image().dataWindow();
int w = dw.max.x - dw.min.x + 1;
- return IMF::Slice (pixelType(),
- (char *) (&_pixels[0][0] -
- dw.min.y / _ySampling * (w / _xSampling) -
- dw.min.x / _xSampling),
- sizeof (T),
- (w / _xSampling) * sizeof (T),
- _xSampling,
- _ySampling);
+ return IMF::Slice::Make (
+ pixelType(),
+ &_pixels[0][0],
+ dw,
+ sizeof(T),
+ (w / _xSampling) * sizeof (T),
+ _xSampling,
+ _ySampling);
}
@@ -227,7 +229,9 @@ template <class T>
void
TypedImageChannel<T>::black ()
{
- memset(&_pixels[0][0],0,image().width()/_xSampling*image().height()/_ySampling*sizeof(T));
+ size_t nx = static_cast<size_t>( image().width() ) / static_cast<size_t>( _xSampling );
+ size_t ny = static_cast<size_t>( image().height() ) / static_cast<size_t>( _ySampling );
+ memset(&_pixels[0][0],0,nx*ny*sizeof(T));
}

View File

@ -1,671 +0,0 @@
Backport of
From 6bad53af7eebed507564dd5fc90320e4c6a6c0bc Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Mon, 20 Jan 2020 09:07:02 +1300
Subject: [PATCH 01/23] Force tile sizes to be less than INT_MAX bytes, in line
with the maximum dimensions of data windows
From df987cabc20c90803692022fd232def837cb88cc Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Mon, 20 Jan 2020 10:52:17 +1300
Subject: [PATCH 02/23] validate tiles have valid headers when raw reading
tiles
From 37750013830def57f19f3c3b7faaa9fc1dae81b3 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Mon, 20 Jan 2020 11:18:55 +1300
Subject: [PATCH 03/23] Sanity check for input buffer overruns in RLE
uncompress
From 3eda5d70aba127bae9bd6bae9956fcf024b64031 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Mon, 20 Jan 2020 14:46:54 +1300
Subject: [PATCH 04/23] fixes for DWA uncompress: sanity check unknown data
reading, off-by-one error on max suffix string length
From b9997d0c045fa01af3d2e46e1a74b07cc4519446 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Mon, 20 Jan 2020 15:39:10 +1300
Subject: [PATCH 06/23] prevent int overflow when calculating buffer offsets
From 7a52d40ae23c148f27116cb1f6e897b9143b372c Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 21 Jan 2020 12:04:13 +1300
Subject: [PATCH 07/23] bypass SSE optimization when skipping subsampled
channels
From 801272c9bf8b84a66c62f1e8a4490ece81da6a56 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 21 Jan 2020 13:33:53 +1300
Subject: [PATCH 08/23] check for bad bit counts in Huff encoded data
From 43cd3ad47d53356da6ae2e983e47c8313aebf72e Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 21 Jan 2020 14:53:23 +1300
Subject: [PATCH 09/23] improve bad count detection in huf decompress
From ea3349896d4a8a3b523e8f3b830334a85240b1e6 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 21 Jan 2020 15:12:58 +1300
Subject: [PATCH 10/23] sanity check data reads from PIZ data
From b1c34c496b62117115b1089b18a44e0031800a09 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Wed, 22 Jan 2020 09:35:46 +1300
Subject: [PATCH 11/23] fix memory leak when reading damaged PIZ files
From e7c26f6ef5bf7ae8ea21ecf19963186cd1391720 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Wed, 22 Jan 2020 17:31:22 +1300
Subject: [PATCH 12/23] abort when file claims to have excessive scanline data
requirements
From a6408c90339bdf19f89476578d7f936b741be9b2 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Thu, 23 Jan 2020 09:40:44 +1300
Subject: [PATCH 13/23] avoid creating compression object just to compute
numLinesInBuffer
From 2ae5f8376b0a6c3e2bb100042f5de79503ba837a Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Thu, 23 Jan 2020 09:52:58 +1300
Subject: [PATCH 14/23] fix check for valid ruleSize
From dea0ef1ee7b2f4d2aa42ffba7b442e5d8051222b Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Thu, 23 Jan 2020 12:30:11 +1300
Subject: [PATCH 15/23] fix memory leak on DeepTiledInput files: compressor for
sample count table wasn't deleted
From d4fbaad4efe5d0ddf325da44ecbab105ebb2954e Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Thu, 23 Jan 2020 12:33:11 +1300
Subject: [PATCH 16/23] fix memory leak in test suite
From 53a06468ef5a08f4f2beb2d264a20547d7a78753 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Thu, 23 Jan 2020 14:44:48 +1300
Subject: [PATCH 17/23] fixes to memory leak when constructors throw exceptions
From b673e6ad0ec6cef94d86b9586244d26088a3d792 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Fri, 24 Jan 2020 08:42:07 +1300
Subject: [PATCH 18/23] Fix cleanup when DeepScanLineInputFile constructor
throws
From acad98d6d3e787f36012a3737c23c42c7f43a00f Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Fri, 24 Jan 2020 13:43:47 +1300
Subject: [PATCH 21/23] missing header for ptrdiff_t
From 0a1aa55ef108169c933ddaa631c1f6cb02b69050 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 28 Jan 2020 18:17:01 +1300
Subject: [PATCH 22/23] minor tweaks and typo fixes
From 89ce46f38c5e658d21df9179c1641c496cab7396 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 28 Jan 2020 18:18:01 +1300
Subject: [PATCH 23/23] force x/y Sampling to 1 for Deep Scanline Images
--- openexr-2.2.1.orig/IlmImf/ImfCompositeDeepScanLine.cpp
+++ openexr-2.2.1/IlmImf/ImfCompositeDeepScanLine.cpp
@@ -179,7 +179,7 @@ CompositeDeepScanLine::Data::handleDeepF
int start,
int end)
{
- int width=_dataWindow.size().x+1;
+ ptrdiff_t width=_dataWindow.size().x+1;
size_t pixelcount = width * (end-start+1);
pointers.resize(_channels.size());
counts.resize(pixelcount);
--- openexr-2.2.1.orig/IlmImf/ImfDeepScanLineInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfDeepScanLineInputFile.cpp
@@ -915,8 +915,7 @@ void DeepScanLineInputFile::initialize(c
}
catch (...)
{
- delete _data;
- _data=NULL;
+ // Don't delete _data here, leave that to caller
throw;
}
}
@@ -932,8 +931,15 @@ DeepScanLineInputFile::DeepScanLineInput
_data->memoryMapped = _data->_streamData->is->isMemoryMapped();
_data->version = part->version;
- initialize(part->header);
-
+ try
+ {
+ initialize(part->header);
+ }
+ catch(...)
+ {
+ delete _data;
+ throw;
+ }
_data->lineOffsets = part->chunkOffsets;
_data->partNumber = part->partNumber;
@@ -945,7 +951,6 @@ DeepScanLineInputFile::DeepScanLineInput
:
_data (new Data (numThreads))
{
- _data->_streamData = new InputStreamMutex();
_data->_deleteStream = true;
OPENEXR_IMF_INTERNAL_NAMESPACE::IStream* is = 0;
@@ -955,12 +960,29 @@ DeepScanLineInputFile::DeepScanLineInput
readMagicNumberAndVersionField(*is, _data->version);
//
// Backward compatibility to read multpart file.
- //
+ // multiPartInitialize will create _streamData
if (isMultiPart(_data->version))
{
compatibilityInitialize(*is);
return;
}
+ }
+ catch (IEX_NAMESPACE::BaseExc &e)
+ {
+ if (is) delete is;
+ if (_data) delete _data;
+
+ REPLACE_EXC (e, "Cannot read image file "
+ "\"" << fileName << "\". " << e.what());
+ throw;
+ }
+
+ //
+ // not multiPart - allocate stream data and intialise as normal
+ //
+ try
+ {
+ _data->_streamData = new InputStreamMutex();
_data->_streamData->is = is;
_data->memoryMapped = is->isMemoryMapped();
_data->header.readFrom (*_data->_streamData->is, _data->version);
@@ -976,7 +998,10 @@ DeepScanLineInputFile::DeepScanLineInput
catch (IEX_NAMESPACE::BaseExc &e)
{
if (is) delete is;
- if (_data && _data->_streamData) delete _data->_streamData;
+ if (_data && _data->_streamData)
+ {
+ delete _data->_streamData;
+ }
if (_data) delete _data;
REPLACE_EXC (e, "Cannot read image file "
@@ -986,7 +1011,10 @@ DeepScanLineInputFile::DeepScanLineInput
catch (...)
{
if (is) delete is;
- if (_data && _data->_streamData) delete _data->_streamData;
+ if (_data && _data->_streamData)
+ {
+ delete _data->_streamData;
+ }
if (_data) delete _data;
throw;
@@ -1010,7 +1038,18 @@ DeepScanLineInputFile::DeepScanLineInput
_data->version =version;
- initialize (header);
+ try
+ {
+ initialize (header);
+ }
+ catch (...)
+ {
+ if (_data && _data->_streamData)
+ {
+ delete _data->_streamData;
+ }
+ if (_data) delete _data;
+ }
readLineOffsets (*_data->_streamData->is,
_data->lineOrder,
@@ -1042,8 +1081,9 @@ DeepScanLineInputFile::~DeepScanLineInpu
//
if (_data->partNumber == -1 && _data->_streamData)
+ {
delete _data->_streamData;
-
+ }
delete _data;
}
}
--- openexr-2.2.1.orig/IlmImf/ImfDeepTiledInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfDeepTiledInputFile.cpp
@@ -283,6 +283,7 @@ DeepTiledInputFile::Data::Data (int numT
multiPartBackwardSupport(false),
numThreads(numThreads),
memoryMapped(false),
+ sampleCountTableComp(NULL),
_streamData(NULL),
_deleteStream(false)
{
@@ -308,6 +309,8 @@ DeepTiledInputFile::Data::~Data ()
for (size_t i = 0; i < slices.size(); i++)
delete slices[i];
+
+ delete sampleCountTableComp;
}
@@ -927,7 +930,15 @@ DeepTiledInputFile::DeepTiledInputFile (
_data (new Data (part->numThreads))
{
_data->_deleteStream=false;
- multiPartInitialize(part);
+ try
+ {
+ multiPartInitialize(part);
+ }
+ catch(...)
+ {
+ delete _data;
+ throw;
+ }
}
--- openexr-2.2.1.orig/IlmImf/ImfDwaCompressor.cpp
+++ openexr-2.2.1/IlmImf/ImfDwaCompressor.cpp
@@ -265,8 +265,9 @@ struct DwaCompressor::Classifier
" (truncated rule).");
{
- char suffix[Name::SIZE];
- memset (suffix, 0, Name::SIZE);
+ // maximum length of string plus one byte for terminating NULL
+ char suffix[Name::SIZE+1];
+ memset (suffix, 0, Name::SIZE+1);
Xdr::read<CharPtrIO> (ptr, std::min(size, Name::SIZE-1), suffix);
_suffix = std::string(suffix);
}
@@ -2409,7 +2410,7 @@ DwaCompressor::uncompress
unsigned short ruleSize = 0;
Xdr::read<CharPtrIO>(dataPtr, ruleSize);
- if (ruleSize < 0)
+ if (ruleSize < Xdr::size<unsigned short>() )
throw Iex::InputExc("Error uncompressing DWA data"
" (corrupt header file).");
@@ -2806,6 +2807,14 @@ DwaCompressor::uncompress
if (Imath::modp (y, cd->ySampling) != 0)
continue;
+ //
+ // sanity check for buffer data lying within range
+ //
+ if (cd->planarUncBufferEnd + dstScanlineSize - _planarUncBuffer[UNKNOWN] > _planarUncBufferSize[UNKNOWN] )
+ {
+ throw Iex::InputExc("DWA data corrupt");
+ }
+
memcpy (rowPtrs[chan][row],
cd->planarUncBufferEnd,
dstScanlineSize);
--- openexr-2.2.1.orig/IlmImf/ImfFastHuf.cpp
+++ openexr-2.2.1/IlmImf/ImfFastHuf.cpp
@@ -256,14 +256,29 @@ FastHufDecoder::FastHufDecoder
int symbol = *i >> 6;
if (mapping[codeLen] >= _numSymbols)
+ {
+ delete[] _idToSymbol;
+ _idToSymbol = NULL;
throw Iex::InputExc ("Huffman decode error "
"(Invalid symbol in header).");
-
+ }
_idToSymbol[mapping[codeLen]] = symbol;
mapping[codeLen]++;
}
- buildTables(base, offset);
+ //
+ // exceptions can be thrown whilst building tables. Delete
+ // _idToSynmbol before re-throwing to prevent memory leak
+ //
+ try
+ {
+ buildTables(base, offset);
+ }catch(...)
+ {
+ delete[] _idToSymbol;
+ _idToSymbol = NULL;
+ throw;
+ }
}
--- openexr-2.2.1.orig/IlmImf/ImfHeader.cpp
+++ openexr-2.2.1/IlmImf/ImfHeader.cpp
@@ -914,7 +914,7 @@ Header::sanityCheck (bool isTiled, bool
const TileDescription &tileDesc = tileDescription();
- if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0)
+ if (tileDesc.xSize <= 0 || tileDesc.ySize <= 0 || tileDesc.xSize > INT_MAX || tileDesc.ySize > INT_MAX )
throw IEX_NAMESPACE::ArgExc ("Invalid tile size in image header.");
if (maxTileWidth > 0 &&
--- openexr-2.2.1.orig/IlmImf/ImfHuf.cpp
+++ openexr-2.2.1/IlmImf/ImfHuf.cpp
@@ -1052,7 +1052,10 @@ hufUncompress (const char compressed[],
unsigned short raw[],
int nRaw)
{
- if (nCompressed == 0)
+ //
+ // nead at least 20 bytes for header
+ //
+ if (nCompressed < 20 )
{
if (nRaw != 0)
notEnoughData();
@@ -1070,6 +1073,12 @@ hufUncompress (const char compressed[],
const char *ptr = compressed + 20;
+ if ( ptr + (nBits+7 )/8 > compressed+nCompressed)
+ {
+ notEnoughData();
+ return;
+ }
+
//
// Fast decoder needs at least 2x64-bits of compressed data, and
// needs to be run-able on this platform. Otherwise, fall back
--- openexr-2.2.1.orig/IlmImf/ImfMisc.cpp
+++ openexr-2.2.1/IlmImf/ImfMisc.cpp
@@ -114,9 +114,9 @@ bytesPerLineTable (const Header &header,
c != channels.end();
++c)
{
- int nBytes = pixelTypeSize (c.channel().type) *
- (dataWindow.max.x - dataWindow.min.x + 1) /
- c.channel().xSampling;
+ size_t nBytes = size_t(pixelTypeSize (c.channel().type)) *
+ size_t(dataWindow.max.x - dataWindow.min.x + 1) /
+ size_t(c.channel().xSampling);
for (int y = dataWindow.min.y, i = 0; y <= dataWindow.max.y; ++y, ++i)
if (modp (y, c.channel().ySampling) == 0)
@@ -262,6 +262,7 @@ defaultFormat (Compressor * compressor)
}
+//obsolete
int
numLinesInBuffer (Compressor * compressor)
{
@@ -1838,6 +1839,39 @@ usesLongNames (const Header &header)
return false;
}
+namespace
+{
+// for a given compression type, return the number of scanlines
+// compressed into a single chunk
+// TODO add to API and move to ImfCompressor.cpp
+int
+numLinesInBuffer(Compression comp)
+{
+ switch(comp)
+ {
+ case NO_COMPRESSION :
+ case RLE_COMPRESSION:
+ case ZIPS_COMPRESSION:
+ return 1;
+ case ZIP_COMPRESSION:
+ return 16;
+ case PIZ_COMPRESSION:
+ return 32;
+ case PXR24_COMPRESSION:
+ return 16;
+ case B44_COMPRESSION:
+ case B44A_COMPRESSION:
+ case DWAA_COMPRESSION:
+ return 32;
+ case DWAB_COMPRESSION:
+ return 256;
+
+ default:
+ throw IEX_NAMESPACE::ArgExc ("Unknown compression type");
+ }
+}
+}
+
int
getScanlineChunkOffsetTableSize(const Header& header)
{
@@ -1847,17 +1881,11 @@ getScanlineChunkOffsetTableSize(const He
size_t maxBytesPerLine = bytesPerLineTable (header,
bytesPerLine);
- Compressor* compressor = newCompressor(header.compression(),
- maxBytesPerLine,
- header);
-
- int linesInBuffer = numLinesInBuffer (compressor);
+ int linesInBuffer = numLinesInBuffer ( header.compression() );
int lineOffsetSize = (dataWindow.max.y - dataWindow.min.y +
linesInBuffer) / linesInBuffer;
- delete compressor;
-
return lineOffsetSize;
}
--- openexr-2.2.1.orig/IlmImf/ImfPizCompressor.cpp
+++ openexr-2.2.1/IlmImf/ImfPizCompressor.cpp
@@ -491,7 +491,9 @@ PizCompressor::uncompress (const char *i
// This is the cunompress function which is used by both the tiled and
// scanline decompression routines.
//
-
+
+ const char* inputEnd=inPtr+inSize;
+
//
// Special case - empty input buffer
//
@@ -502,6 +504,7 @@ PizCompressor::uncompress (const char *i
return 0;
}
+
//
// Determine the layout of the compressed pixel data
//
@@ -548,6 +551,12 @@ PizCompressor::uncompress (const char *i
AutoArray <unsigned char, BITMAP_SIZE> bitmap;
memset (bitmap, 0, sizeof (unsigned char) * BITMAP_SIZE);
+
+ if(inPtr + sizeof(unsigned short)*2 > inputEnd)
+ {
+ throw InputExc ("PIZ compressed data too short");
+ }
+
Xdr::read <CharPtrIO> (inPtr, minNonZero);
Xdr::read <CharPtrIO> (inPtr, maxNonZero);
@@ -559,8 +568,14 @@ PizCompressor::uncompress (const char *i
if (minNonZero <= maxNonZero)
{
- Xdr::read <CharPtrIO> (inPtr, (char *) &bitmap[0] + minNonZero,
- maxNonZero - minNonZero + 1);
+ size_t bytesToRead = maxNonZero - minNonZero + 1;
+ if(inPtr + bytesToRead > inputEnd)
+ {
+ throw InputExc ("PIZ compressed data too short");
+ }
+
+Xdr::read <CharPtrIO> (inPtr, (char *) &bitmap[0] + minNonZero,
+ bytesToRead);
}
AutoArray <unsigned short, USHORT_RANGE> lut;
@@ -569,6 +584,11 @@ PizCompressor::uncompress (const char *i
//
// Huffman decoding
//
+ if(inPtr + sizeof(int)> inputEnd)
+ {
+ throw InputExc ("PIZ compressed data too short");
+ }
+
int length;
Xdr::read <CharPtrIO> (inPtr, length);
--- openexr-2.2.1.orig/IlmImf/ImfRle.cpp
+++ openexr-2.2.1/IlmImf/ImfRle.cpp
@@ -129,6 +129,11 @@ rleUncompress (int inLength, int maxLeng
if (0 > (maxLength -= count))
return 0;
+ // check the input buffer is big enough to contain
+ // 'count' bytes of remaining data
+ if (inLength < 0)
+ return 0;
+
memcpy(out, in, count);
out += count;
in += count;
--- openexr-2.2.1.orig/IlmImf/ImfScanLineInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfScanLineInputFile.cpp
@@ -1114,6 +1114,12 @@ void ScanLineInputFile::initialize(const
size_t maxBytesPerLine = bytesPerLineTable (_data->header,
_data->bytesPerLine);
+
+ if(maxBytesPerLine > INT_MAX)
+ {
+ throw IEX_NAMESPACE::InputExc("maximum bytes per scanline exceeds maximum permissible size");
+ }
+
for (size_t i = 0; i < _data->lineBuffers.size(); i++)
{
@@ -1148,6 +1154,8 @@ void ScanLineInputFile::initialize(const
}
catch (...)
{
+ if (_data->partNumber == -1)
+ delete _streamData;
delete _data;
_data=NULL;
throw;
@@ -1420,6 +1428,14 @@ ScanLineInputFile::setFrameBuffer (const
offset+=2;
break;
}
+
+ //
+ // optimization mode cannot currently skip subsampled channels
+ //
+ if (i.channel().xSampling!=1 || i.channel().ySampling!=1)
+ {
+ optimizationPossible = false;
+ }
++i;
}
--- openexr-2.2.1.orig/IlmImf/ImfTiledInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfTiledInputFile.cpp
@@ -736,7 +736,10 @@ TiledInputFile::TiledInputFile (const ch
delete _data->_streamData;
}
-
+ if (_data)
+ {
+ delete _data;
+ }
if (is != 0)
delete is;
@@ -759,6 +762,10 @@ TiledInputFile::TiledInputFile (const ch
if (is != 0)
delete is;
+ if (_data)
+ {
+ delete _data;
+ }
throw;
}
}
@@ -846,7 +853,15 @@ TiledInputFile::TiledInputFile (InputPar
{
_data = new Data (part->numThreads);
_data->_deleteStream=false;
- multiPartInitialize(part);
+ try
+ {
+ multiPartInitialize(part);
+ }
+ catch(...)
+ {
+ if (_data) delete _data;
+ throw;
+ }
}
@@ -1307,6 +1322,11 @@ TiledInputFile::rawTileData (int &dx, in
readNextTileData (_data->_streamData, _data, dx, dy, lx, ly,
tileBuffer->buffer,
pixelDataSize);
+
+ if ( !isValidLevel(lx,ly) || !isValidTile (dx, dy, lx, ly) )
+ throw IEX_NAMESPACE::ArgExc ("File contains an invalid tile");
+
+
if(isMultiPart(version()))
{
if (old_dx!=dx || old_dy !=dy || old_lx!=lx || old_ly!=ly)
--- openexr-2.2.1.orig/IlmImfTest/testMultiPartApi.cpp
+++ openexr-2.2.1/IlmImfTest/testMultiPartApi.cpp
@@ -450,6 +450,21 @@ generateRandomFile (int partCount, const
}
}
+ for (size_t i = 0 ; i < parts.size() ; ++i )
+ {
+ int partType = partTypes[i];
+
+ if (partType == 0)
+ {
+ delete (OutputPart*) parts[i];
+ }
+ else
+ {
+ delete (TiledOutputPart*) parts[i];
+ }
+
+ }
+
delete[] tiledHalfData;
delete[] tiledUintData;
delete[] tiledFloatData;

View File

@ -1,16 +0,0 @@
From 3d03979dc101612e806cdf0b011475d9fa685a73 Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
Date: Tue, 19 May 2020 16:09:21 +1200
Subject: [PATCH] fix #728 - missing 'throw' in deepscanline error handling
--- openexr-2.2.1.orig/IlmImf/ImfDeepScanLineInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfDeepScanLineInputFile.cpp
@@ -1049,6 +1049,8 @@ DeepScanLineInputFile::DeepScanLineInput
delete _data->_streamData;
}
if (_data) delete _data;
+
+ throw;
}
readLineOffsets (*_data->_streamData->is,

View File

@ -1,130 +0,0 @@
From 6a9f8af6e89547bcd370ae3cec2b12849eee0b54 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
Date: Wed, 27 May 2020 13:50:54 +1200
Subject: [PATCH] always ignore chunkCount attribute unless it cannot be
computed (#738)
--- openexr-2.2.1.orig/IlmImf/ImfDeepTiledOutputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfDeepTiledOutputFile.cpp
@@ -1228,7 +1228,7 @@ DeepTiledOutputFile::initialize (const H
_data->numYTiles);
//ignore the existing value of chunkCount - correct it if it's wrong
- _data->header.setChunkCount(getChunkOffsetTableSize(_data->header,true));
+ _data->header.setChunkCount(getChunkOffsetTableSize(_data->header));
_data->maxSampleCountTableSize = _data->tileDesc.ySize *
_data->tileDesc.xSize *
--- openexr-2.2.1.orig/IlmImf/ImfMisc.cpp
+++ openexr-2.2.1/IlmImf/ImfMisc.cpp
@@ -1896,18 +1896,30 @@ int
getTiledChunkOffsetTableSize(const Header& header);
int
-getChunkOffsetTableSize(const Header& header,bool ignore_attribute)
+getChunkOffsetTableSize(const Header& header,bool)
{
- if(!ignore_attribute && header.hasChunkCount())
- {
- return header.chunkCount();
- }
-
+ //
+ // if there is a type in the header which indicates the part is not a currently supported type,
+ // use the chunkCount attribute
+ //
+
+
if(header.hasType() && !isSupportedType(header.type()))
{
- throw IEX_NAMESPACE::ArgExc ("unsupported header type to "
- "get chunk offset table size");
+ if(header.hasChunkCount())
+ {
+ return header.chunkCount();
+ }
+ else
+ {
+ throw IEX_NAMESPACE::ArgExc ("unsupported header type to "
+ "get chunk offset table size");
+ }
}
+
+ //
+ // part is a known type - ignore the header attribute and compute the chunk size from the header
+ //
if (isTiled(header.type()) == false)
return getScanlineChunkOffsetTableSize(header);
else
--- openexr-2.2.1.orig/IlmImf/ImfMisc.h
+++ openexr-2.2.1/IlmImf/ImfMisc.h
@@ -452,13 +452,16 @@ bool usesLongNames (const Header &header
//
-// compute size of chunk offset table - if ignore_attribute set to true
-// will compute from the image size and layout, rather than the attribute
-// The default behaviour is to read the attribute
+// compute size of chunk offset table - for existing types, computes
+// the chunk size from the image size, compression type, and tile description
+// (for tiled types). If the type is not supported, uses the chunkCount attribute
+// if present, or throws an exception otherwise
+// deprecated_attribute is no longer used by this function
+//
//
IMF_EXPORT
-int getChunkOffsetTableSize(const Header& header,bool ignore_attribute=false);
+int getChunkOffsetTableSize(const Header& header,bool deprecated_attribute=false);
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
--- openexr-2.2.1.orig/IlmImf/ImfMultiPartInputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfMultiPartInputFile.cpp
@@ -735,7 +735,7 @@ MultiPartInputFile::Data::readChunkOffse
for (size_t i = 0; i < parts.size(); i++)
{
- int chunkOffsetTableSize = getChunkOffsetTableSize(parts[i]->header,false);
+ int chunkOffsetTableSize = getChunkOffsetTableSize(parts[i]->header);
parts[i]->chunkOffsets.resize(chunkOffsetTableSize);
for (int j = 0; j < chunkOffsetTableSize; j++)
--- openexr-2.2.1.orig/IlmImf/ImfMultiPartOutputFile.cpp
+++ openexr-2.2.1/IlmImf/ImfMultiPartOutputFile.cpp
@@ -145,7 +145,7 @@ MultiPartOutputFile::Data::do_header_san
if (isMultiPart)
{
// multipart files must contain a chunkCount attribute
- _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0],true));
+ _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0]));
for (size_t i = 1; i < parts; i++)
{
@@ -153,7 +153,7 @@ MultiPartOutputFile::Data::do_header_san
throw IEX_NAMESPACE::ArgExc ("Every header in a multipart file should have a type");
- _headers[i].setChunkCount(getChunkOffsetTableSize(_headers[i],true));
+ _headers[i].setChunkCount(getChunkOffsetTableSize(_headers[i]));
_headers[i].sanityCheck (_headers[i].hasTileDescription(), isMultiPart);
@@ -185,7 +185,7 @@ MultiPartOutputFile::Data::do_header_san
if (_headers[0].hasType() && isImage(_headers[0].type()) == false)
{
- _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0],true));
+ _headers[0].setChunkCount(getChunkOffsetTableSize(_headers[0]));
}
}
@@ -494,7 +494,7 @@ MultiPartOutputFile::Data::writeChunkTab
{
for (size_t i = 0; i < parts.size(); i++)
{
- int chunkTableSize = getChunkOffsetTableSize(parts[i]->header,false);
+ int chunkTableSize = getChunkOffsetTableSize(parts[i]->header);
Int64 pos = os->tellp();

View File

@ -1,26 +0,0 @@
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 <peterh@wetafx.co.nz>
---
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

View File

@ -1,34 +0,0 @@
From ae6d203892cc9311917a7f4f05354ef792b3e58e Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
Date: Thu, 3 Dec 2020 10:53:32 +1300
Subject: [PATCH] Handle xsampling and bad seekg() calls in exrcheck (#872)
* fix exrcheck xsampling!=1
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
* fix handling bad seekg() calls in exrcheck
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
* fix deeptile detection in multipart files
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
---
src/lib/OpenEXR/ImfDeepTiledInputFile.cpp | 2 +-
src/lib/OpenEXRUtil/ImfCheckFile.cpp | 20 ++++++++++++--------
2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp b/src/lib/OpenEXR/ImfDeepTiledInputFile.cpp
index f5abe9c6a..94452905c 100644
--- a/IlmImf/ImfDeepTiledInputFile.cpp
+++ b/IlmImf/ImfDeepTiledInputFile.cpp
@@ -960,7 +960,7 @@ DeepTiledInputFile::compatibilityInitialize(OPENEXR_IMF_INTERNAL_NAMESPACE::IStr
void
DeepTiledInputFile::multiPartInitialize(InputPartData* part)
{
- if (isTiled(part->header.type()) == false)
+ if (part->header.type() != DEEPTILE)
THROW (IEX_NAMESPACE::ArgExc, "Can't build a DeepTiledInputFile from a part of type " << part->header.type());
_data->_streamData = part->mutex;

View File

@ -1,83 +0,0 @@
From 1f7cac0d1538544d3f93353bc16750374aea33b8 Mon Sep 17 00:00:00 2001
From: jackie_wu <wutao61@huawei.com>
Date: Fri, 18 Jun 2021 16:31:51 +0800
Subject: [PATCH] add
---
IlmImf/ImfDwaCompressor.cpp | 21 ++++++++++-----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/IlmImf/ImfDwaCompressor.cpp b/IlmImf/ImfDwaCompressor.cpp
index 1c1bd45..424cc46 100644
--- a/IlmImf/ImfDwaCompressor.cpp
+++ b/IlmImf/ImfDwaCompressor.cpp
@@ -2905,8 +2905,8 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
int maxOutBufferSize = 0;
int numLossyDctChans = 0;
- int unknownBufferSize = 0;
- int rleBufferSize = 0;
+ size_t unknownBufferSize = 0;
+ size_t rleBufferSize = 0;
int maxLossyDctAcSize = (int)ceil ((float)numScanLines() / 8.0f) *
(int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
@@ -2916,6 +2916,9 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
(int)ceil ((float)(_max[0] - _min[0] + 1) / 8.0f) *
sizeof (unsigned short);
+
+ size_t pixelCount = static_cast<size_t>(numScanLines()) * static_cast<size_t>(_max[0] - _min[0] + 1);
+
for (unsigned int chan = 0; chan < _channelData.size(); ++chan)
{
switch (_channelData[chan].compression)
@@ -2939,8 +2942,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
// of the source data.
//
- int rleAmount = 2 * numScanLines() * (_max[0] - _min[0] + 1) *
- Imf::pixelTypeSize (_channelData[chan].type);
+ size_t rleAmount = 2 * pixelCount * Imf::pixelTypeSize (_channelData[chan].type);
rleBufferSize += rleAmount;
}
@@ -2949,8 +2951,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
case UNKNOWN:
- unknownBufferSize += numScanLines() * (_max[0] - _min[0] + 1) *
- Imf::pixelTypeSize (_channelData[chan].type);
+ unknownBufferSize += pixelCount * Imf::pixelTypeSize (_channelData[chan].type);
break;
default:
@@ -3059,7 +3060,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
// all in one swoop (for each compression scheme).
//
- int planarUncBufferSize[NUM_COMPRESSOR_SCHEMES];
+ size_t planarUncBufferSize[NUM_COMPRESSOR_SCHEMES];
for (int i=0; i<NUM_COMPRESSOR_SCHEMES; ++i)
planarUncBufferSize[i] = 0;
@@ -3071,14 +3072,12 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
break;
case RLE:
- planarUncBufferSize[RLE] +=
- numScanLines() * (_max[0] - _min[0] + 1) *
+ planarUncBufferSize[RLE] += pixelCount *
Imf::pixelTypeSize (_channelData[chan].type);
break;
case UNKNOWN:
- planarUncBufferSize[UNKNOWN] +=
- numScanLines() * (_max[0] - _min[0] + 1) *
+ planarUncBufferSize[UNKNOWN] += pixelCount *
Imf::pixelTypeSize (_channelData[chan].type);
break;
--
2.23.0

View File

@ -1,41 +0,0 @@
From ca5ad034786d75ad9e9f0370a87bbb6ddfe35f86 Mon Sep 17 00:00:00 2001
From: = <=>
Date: Tue, 22 Jun 2021 14:47:31 +0800
Subject: [PATCH] add
---
IlmImf/ImfDwaCompressor.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/IlmImf/ImfDwaCompressor.cpp b/IlmImf/ImfDwaCompressor.cpp
index ddd8b3c..4aa0d58 100644
--- a/IlmImf/ImfDwaCompressor.cpp
+++ b/IlmImf/ImfDwaCompressor.cpp
@@ -2908,7 +2908,7 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
// of channels we have.
//
- int maxOutBufferSize = 0;
+ size_t maxOutBufferSize = 0;
int numLossyDctChans = 0;
size_t unknownBufferSize = 0;
size_t rleBufferSize = 0;
@@ -2973,13 +2973,13 @@ DwaCompressor::initializeBuffers (size_t &outBufferSize)
// which could take slightly more space
//
- maxOutBufferSize += (int)(ceil (1.01f * (float)rleBufferSize) + 100);
+ maxOutBufferSize += ceil (1.01f * (float)rleBufferSize) + 100;
//
// And the same goes for the UNKNOWN data
//
- maxOutBufferSize += (int)(ceil (1.01f * (float)unknownBufferSize) + 100);
+ maxOutBufferSize += ceil (1.01f * (float)unknownBufferSize) + 100;
//
// Allocate a zip/deflate compressor big enought to hold the DC data
--
2.23.0

View File

@ -1,33 +0,0 @@
From c3ed4a1db1f39bf4524a644cb2af81dc8cfab33f Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
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 <peterh@wetafx.co.nz>
---
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);
}

View File

@ -1,27 +0,0 @@
From d548fd5eb04d62ad65db18e6425a36e7ab6645dc Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Sat, 8 Aug 2020 16:27:03 -0700
Subject: [PATCH] Avoid integer overflow in calculateNumTiles()
Signed-off-by: Cary Phillips <cary@ilm.com>
---
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<int>::max() - size + 1)
+ throw IEX_NAMESPACE::ArgExc ("Invalid size.");
+
+ numTiles[i] = (l + size - 1) / size;
}
}

View File

@ -1,29 +0,0 @@
From 46833b0e090a31cdccc32cad1ca27fe601d79875 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Sat, 8 Aug 2020 16:34:02 -0700
Subject: [PATCH] Change >= to > in overflow calculation
Signed-off-by: Cary Phillips <cary@ilm.com>
---
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<int>::max() - size + 1)
+ int l = levelSize (min, max, i, rmode);
+ if (l > std::numeric_limits<int>::max() - size + 1)
throw IEX_NAMESPACE::ArgExc ("Invalid size.");
- numTiles[i] = (l + size - 1) / size;
+ numTiles[i] = (l + size - 1) / size;
}
}

View File

@ -1,35 +0,0 @@
From 2a18ed424a854598c2a20b5dd7e782b436a1e753 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
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 <cary@ilm.com>
* Compute level size with 64 bits to avoid overflow
Signed-off-by: Cary Phillips <cary@ilm.com>
---
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<int>::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;
}
}

View File

@ -1,70 +0,0 @@
From eec0dba242bedd2778c973ae4af112107b33d9c9 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
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 <peterh@wetafx.co.nz>
---
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;

View File

@ -1,25 +0,0 @@
From 467be80b75642efbbe6bdace558079f68c16acb1 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
Date: Tue, 10 Nov 2020 08:35:59 +1300
Subject: [PATCH] Fix overflow computing deeptile sample table size (#861)
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
---
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<size_t>(_data->tileDesc.ySize) *
+ static_cast<size_t>(_data->tileDesc.xSize) *
sizeof(int);
_data->sampleCountTableBuffer.resizeErase(_data->maxSampleCountTableSize);

View File

@ -1,35 +0,0 @@
From bc88cdb6c97fbf5bc5d11ad8ca55306da931283a Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
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 <peterh@wetafx.co.nz>
Co-authored-by: Cary Phillips <cary@ilm.com>
---
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));

View File

@ -1,174 +0,0 @@
From 969907789e687469a9ee5c003656f761e77fe15d Mon Sep 17 00:00:00 2001
From: Peter Hillman <peterh@wetafx.co.nz>
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 <CharPtrIO> (writePtr, *(const float *) readPtr);
+ union bytesOrFloat tmp;
+ tmp.b = * reinterpret_cast<const FBytes *>( readPtr );
+ Xdr::write <CharPtrIO> (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<class T> 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<activechans)
{
@@ -419,6 +456,7 @@ setupBuffer (const Header& hdr, // header to grab datawindow from
1,1,0.4));
char * pre_offset = offset-&readingBuffer[0]+&preReadBuffer[0];
+
prereadbuf.insert (passivechannels[i-activechans],
Slice (type,
pre_offset,

View File

@ -1,171 +0,0 @@
From 7f8c2414d8fa0cc2ccfdcb236697f4bd806d81a6 Mon Sep 17 00:00:00 2001
From: wang_yue111 <648774160@qq.com>
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 <peterh@wetafx.co.nz>
Co-authored-by: Cary Phillips <cary@ilm.com>
---
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<Rgba*>(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

View File

@ -1,680 +0,0 @@
From 3c05eacda70e3ac00ca45287aa4c8de7262a0673 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
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 <peterh@wetafx.co.nz>
* Use intptr_t in pointer math with negatives (pointer overflow behavior undefined)
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
* fix undefined behavior reading non-aligned 32/64 bit ints
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
* fix undefined behavior warnings in IlmImfTest
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
* cleaner pointer casting/typo fix
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
---
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<intptr_t>(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<float*>(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<half*>(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<StreamIO> (*_data->_streamData->is, *(Int64 *) (pixelData+20));
-
+ Xdr::read<StreamIO> (*_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<char*> (const_cast<void *> (ptr));
+ intptr_t base = reinterpret_cast<intptr_t> (const_cast<void *> (ptr));
if (xStride == 0)
{
switch (type)
@@ -117,7 +117,7 @@ Slice::Make (
return Slice (
type,
- base - offx - offy,
+ reinterpret_cast<char*>(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<intptr_t>(fromSlice.base);
+ intptr_t toBase = reinterpret_cast<intptr_t>(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<char*> (fromBase +
(y - tileRange.min.y) * fromSlice.yStride +
- xStart * fromSlice.xStride;
+ xStart * fromSlice.xStride);
- toPtr = toSlice.base +
+ toPtr = reinterpret_cast<char*> (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 <CharPtrIO> (writePtr, *(const unsigned int *) readPtr);
+ union bytesUintOrFloat tmp;
+ tmp.b = * reinterpret_cast<const FBytes *>( readPtr );
+ Xdr::write <CharPtrIO> (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<const FBytes *>( readPtr );
Xdr::write <CharPtrIO> (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<intptr_t>(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<const char*>(linePtr +
+ dMinX * slice.xStride);
+ const char *endPtr = reinterpret_cast<const char*>(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<intptr_t>(_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<Rgba*>(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<intptr_t>(_fbBase);
+
for (int j = 0; j < _width; ++j)
{
- _tmpBuf[j + N2] = _fbBase[_fbYStride * _currentScanLine +
- _fbXStride * (j + _xMin)];
+ const Rgba* ptr = reinterpret_cast<const Rgba*>(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<intptr_t>(_fbBase);
+ for (int i = 0; i < _width; ++i)
+ {
+ Rgba* ptr = reinterpret_cast<Rgba*>(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<intptr_t>(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<Rgba*>(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<intptr_t>(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<char*> (linePtr + intptr_t( dMinX ) * intptr_t( slice.xStride ));
+ char *endPtr = reinterpret_cast<char*> (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<intptr_t>(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<unsigned short*>(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<intptr_t>(slice.base);
+ char *writePtr = reinterpret_cast<char*>(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<intptr_t>(slice.base);
+ const char *readPtr = reinterpret_cast<const char*>(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<intptr_t>(_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<Rgba*>(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<intptr_t>(_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<Rgba*>(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<intptr_t>(&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<char*>(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<intptr_t>(i.slice().base);
+ char * ptr = reinterpret_cast<char*>(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<intptr_t>( p.slice().base);
+ char * ptr = reinterpret_cast<char*>(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 ();
+
}

View File

@ -1,550 +0,0 @@
From d80f11f4f55100d007ae80a162bf257ec291612c Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
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 <peterh@wetafx.co.nz>
* handle edge-case of empty framebuffer
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
---
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<intptr_t>(fromSlice.base);
+ FrameBuffer::ConstIterator c = ifd->cachedBuffer->find(k.name());
intptr_t toBase = reinterpret_cast<intptr_t>(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<intptr_t>(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<char*> (fromBase +
+ (y - tileRange.min.y) * fromSlice.yStride +
+ xStart * fromSlice.xStride);
+
+ toPtr = reinterpret_cast<char*> (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<char*> (fromBase +
- (y - tileRange.min.y) * fromSlice.yStride +
- xStart * fromSlice.xStride);
-
- toPtr = reinterpret_cast<char*> (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<char*> (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<unsigned int*>(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<half*>(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<float*>(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<unsigned int> &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<unsigned int> &pi1,
Array2D<half> ph2 (h, w);
Array2D<float> pf2 (h, w);
+ Array2D<unsigned int> fi2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<half> fh2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<float> 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<unsigned int> &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<unsigned int> &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<unsigned int> &pi1,
Array2D<half> ph2 (h, w);
Array2D<float> pf2 (h, w);
+ Array2D<unsigned int> fi2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<half> fh2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<float> ff2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+
FrameBuffer fb;
fb.insert ("I", // name
@@ -364,6 +411,34 @@ writeRead (const Array2D<unsigned int> &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<unsigned int> &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<unsigned int> &pi1,
Array2D<half> ph2 (h, w);
Array2D<float> pf2 (h, w);
+
+ Array2D<unsigned int> fi2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<half> fh2 (fillChannel ? h : 1 , fillChannel ? w : 1);
+ Array2D<float> 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<unsigned int> &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<unsigned int> &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

View File

@ -1,26 +0,0 @@
From e2667ae1a3ff8a9fce730e61129868b326abb3f5 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
Date: Fri, 4 Jun 2021 11:13:49 +1200
Subject: [PATCH] verify data size in deepscanlines with NO_COMPRESSION (#1037)
Signed-off-by: Peter Hillman <peterh@wetafx.co.nz>
---
IlmImf/ImfDeepScanLineInputFile.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/IlmImf/ImfDeepScanLineInputFile.cpp b/IlmImf/ImfDeepScanLineInputFile.cpp
index 5f0f43989..ead43c729 100644
--- a/IlmImf/ImfDeepScanLineInputFile.cpp
+++ b/IlmImf/ImfDeepScanLineInputFile.cpp
@@ -647,6 +647,11 @@ LineBufferTask::execute ()
_lineBuffer->format = Compressor::XDR;
_lineBuffer->uncompressedData = _lineBuffer->buffer;
+
+ if(_lineBuffer->packedDataSize!=maxBytesPerLine)
+ {
+ THROW (IEX_NAMESPACE::InputExc, "Incorrect size for uncompressed data. Expected " << maxBytesPerLine << " got " << _lineBuffer->packedDataSize << " bytes");
+ }
}
}

View File

@ -1,27 +0,0 @@
From 2a4f6d9ecd0c9ab2dfaf6bdb99ec962aa1ad09e9 Mon Sep 17 00:00:00 2001
From: peterhillman <peterh@wetafx.co.nz>
Date: Fri,4 Jun 2021 11:12:16 +1200
Subject: [PATCH] detect buffer overflow in RleUncompress(#1036)
---
IlmImf/ImfRle.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/IlmImf/ImfRle.cpp b/IlmImf/ImfRle.cpp
index f6992fa..458f261 100644
--- a/IlmImf/ImfRle.cpp
+++ b/IlmImf/ImfRle.cpp
@@ -145,6 +145,10 @@ rleUncompress (int inLength, int maxLength, const signed char in[], char out[])
if (0 > (maxLength -= count + 1))
return 0;
+ //check the input buffer is big enough to contain
+ //byte to be duplicated
+ if (inLength < 0)
+ return 0;
memset(out, *(char*)in, count+1);
out += count+1;
--
2.27.0

View File

@ -1,36 +1,12 @@
Name: OpenEXR
Summary: A high dynamic-range (HDR) image file format for use in computer imaging applications
Version: 2.2.0
Release: 23
Version: 3.1.3
Release: 1
License: BSD
URL: http://www.openexr.com/
Source0: http://download.savannah.nongnu.org/releases/openexr/openexr-%{version}.tar.gz
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
Patch0014: CVE-2021-23215.patch
Patch0015: CVE-2021-23169.patch
Patch0016: CVE-2021-26260.patch
Patch0017: CVE-2021-3598.patch
Patch0018: CVE-2020-11758-to-CVE-2020-11765.patch
Patch0019: CVE-2020-15305.patch
Patch0020: CVE-2020-15306.patch
Patch0021: CVE-2021-3605.patch
BuildConflicts: %{name}-devel < 2.2.0
BuildRequires: gcc-c++ ilmbase-devel >= %{version} zlib-devel pkgconfig
Source0: https://github.com/AcademySoftwareFoundation/openexr/archive/v%{version}/openexr-%{version}.tar.gz
BuildRequires: gcc-c++ zlib-devel pkgconfig python3-devel
BuildRequires: cmake gcc boost-devel pkgconfig(Imath)
Requires: %{name}-libs = %{version}-%{release}
@ -43,6 +19,8 @@ Light & Magic for use in computer imaging applications.
%package libs
Summary: Libraries for %{name}
Provides: openexr-libs = %{version}-%{release}
Obsoletes: openexr-libs < %{version}-%{release}
%description libs
Libraries for %{name}.
@ -51,7 +29,9 @@ Libraries for %{name}.
Summary: Development files for %{name}
Provides: openexr-devel = %{version}-%{release}
Obsoletes: openexr-devel < %{version}-%{release}
Requires: %{name}-libs = %{version}-%{release} ilmbase-devel
Provides: ilmbase-devel = %{version}-%{release}
Obsoletes: ilmbase-devel < 2.5.3
Requires: %{name}-libs = %{version}-%{release}
%description devel
This package contains libraries and header files for development of %{name}.
@ -60,37 +40,37 @@ This package contains libraries and header files for development of %{name}.
%autosetup -n openexr-%{version} -p1
%build
%configure --disable-static
%cmake
%make_build
%install
%make_install
%delete_la
%check
export PKG_CONFIG_PATH="%{buildroot}%{_libdir}/pkgconfig${PKG_CONFIG_PATH:+:}${PKG_CONFIG_PATH}"
test "$(pkg-config --modversion OpenEXR)" = "%{version}"
%make_build check ||:
%make_build test
%ldconfig_scriptlets libs
%files
%doc AUTHORS ChangeLog NEWS README
%license LICENSE
%{_bindir}/exr*
%doc CHANGES.md CONTRIBUTING.md GOVERNANCE.md SECURITY.md CODE_OF_CONDUCT.md CONTRIBUTORS.md README.md
%license LICENSE.md
%{_bindir}/*
%exclude %{_docdir}/%{name}-%{version}
%files libs
%{_libdir}/libIlmImf-2_2.so.22*
%{_libdir}/libIlmImfUtil-2_2.so.22*
%{_libdir}/*.so.30*
%files devel
%{_datadir}/aclocal/openexr.m4
%{_includedir}/%{name}/*
%{_libdir}/libIlmImf*.so
%{_docdir}/OpenEXR/
%{_includedir}/OpenEXR/
%{_libdir}/*.so
%{_libdir}/cmake/OpenEXR/
%{_libdir}/pkgconfig/OpenEXR.pc
%changelog
* Mon Feb 7 2022 liyanan <liyanan32@huawei.com> - 3.1.3-1
- update to 3.1.3
* Wed Sat 1 2021 liwu<liwu13@huawei.com> - 2.2.0-23
- fix CVE-2021-3605

View File

@ -1,63 +0,0 @@
diff -up openexr-2.1.0/IlmImfTest/testFutureProofing.cpp.bigendian openexr-2.1.0/IlmImfTest/testFutureProofing.cpp
--- openexr-2.1.0/IlmImfTest/testFutureProofing.cpp.bigendian 2013-11-11 17:09:51.000000000 -0600
+++ openexr-2.1.0/IlmImfTest/testFutureProofing.cpp 2013-11-27 08:43:55.486026741 -0600
@@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <byteswap.h>
#include "tmpDir.h"
#include "testFutureProofing.h"
@@ -64,6 +65,7 @@
#include <ImfNamespace.h>
#include <ImathNamespace.h>
#include <IlmThreadNamespace.h>
+#include <ImfSystemSpecific.h>
namespace IMF = OPENEXR_IMF_NAMESPACE;
using namespace IMF;
@@ -1234,6 +1236,12 @@ modifyType (bool modify_version)
//length of attribute
fread(&length,4,1,f);
+ if (!GLOBAL_SYSTEM_LITTLE_ENDIAN)
+ {
+ int tmp = bswap_32(length);
+ length = tmp;
+ }
+
if(!modify_version && attrib_name=="type")
{
// modify the type of part 1 to be 'X<whatevever>'
diff -up openexr-2.1.0/IlmImfTest/testMultiPartFileMixingBasic.cpp.bigendian openexr-2.1.0/IlmImfTest/testMultiPartFileMixingBasic.cpp
--- openexr-2.1.0/IlmImfTest/testMultiPartFileMixingBasic.cpp.bigendian 2013-11-11 17:09:52.000000000 -0600
+++ openexr-2.1.0/IlmImfTest/testMultiPartFileMixingBasic.cpp 2013-11-27 08:44:19.370775892 -0600
@@ -40,6 +40,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
+#include <byteswap.h>
#include "tmpDir.h"
#include "testMultiPartFileMixingBasic.h"
@@ -59,6 +60,7 @@
#include <ImfDeepScanLineInputPart.h>
#include <ImfPartType.h>
#include <ImfMisc.h>
+#include <ImfSystemSpecific.h>
namespace IMF = OPENEXR_IMF_NAMESPACE;
using namespace IMF;
@@ -1383,6 +1385,11 @@ killOffsetTables (const std::string & fn
//length of attribute
fread(&length,4,1,f);
+ if (!GLOBAL_SYSTEM_LITTLE_ENDIAN)
+ {
+ int tmp = bswap_32(length);
+ length = tmp;
+ }
//value of attribute
for(int i=0;i<length;i++)