diff --git a/baselibs.conf b/baselibs.conf index 533e803..1278a5a 100644 --- a/baselibs.conf +++ b/baselibs.conf @@ -1,5 +1,5 @@ -libOpenEXR-3_1-30 -libOpenEXRCore-3_1-30 -libOpenEXRUtil-3_1-30 -libIlmThread-3_1-30 -libIex-3_1-30 +libOpenEXR-3_2-31 +libOpenEXRCore-3_2-31 +libOpenEXRUtil-3_2-31 +libIlmThread-3_2-31 +libIex-3_2-31 diff --git a/openexr-CVE-2023-5841.patch b/openexr-CVE-2023-5841.patch new file mode 100644 index 0000000..b7939ee --- /dev/null +++ b/openexr-CVE-2023-5841.patch @@ -0,0 +1,466 @@ +diff --git a/src/lib/OpenEXRCore/decoding.c b/src/lib/OpenEXRCore/decoding.c +index 322cbd896..710d8a6db 100644 +--- a/src/lib/OpenEXRCore/decoding.c ++++ b/src/lib/OpenEXRCore/decoding.c +@@ -288,6 +288,9 @@ default_decompress_chunk (exr_decode_pipeline_t* decode) + uint64_t sampsize = + (((uint64_t) decode->chunk.width) * + ((uint64_t) decode->chunk.height)); ++ ++ if ((decode->decode_flags & EXR_DECODE_SAMPLE_COUNTS_AS_INDIVIDUAL)) ++ sampsize += 1; + sampsize *= sizeof (int32_t); + + rv = decompress_data ( +@@ -340,7 +343,7 @@ unpack_sample_table ( + exr_result_t rv = EXR_ERR_SUCCESS; + int32_t w = decode->chunk.width; + int32_t h = decode->chunk.height; +- int32_t totsamp = 0; ++ uint64_t totsamp = 0; + int32_t* samptable = decode->sample_count_table; + size_t combSampSize = 0; + +@@ -351,38 +354,44 @@ unpack_sample_table ( + { + for (int32_t y = 0; y < h; ++y) + { ++ int32_t *cursampline = samptable + y * w; + int32_t prevsamp = 0; + for (int32_t x = 0; x < w; ++x) + { + int32_t nsamps = +- (int32_t) one_to_native32 ((uint32_t) samptable[y * w + x]); +- if (nsamps < 0) return EXR_ERR_INVALID_SAMPLE_DATA; +- samptable[y * w + x] = nsamps - prevsamp; +- prevsamp = nsamps; ++ (int32_t) one_to_native32 ((uint32_t) cursampline[x]); ++ if (nsamps < prevsamp) return EXR_ERR_INVALID_SAMPLE_DATA; ++ ++ cursampline[x] = nsamps - prevsamp; ++ prevsamp = nsamps; + } +- totsamp += prevsamp; ++ totsamp += (uint64_t)prevsamp; + } +- samptable[w * h] = totsamp; ++ if (totsamp >= (uint64_t)INT32_MAX) ++ return EXR_ERR_INVALID_SAMPLE_DATA; ++ samptable[w * h] = (int32_t)totsamp; + } + else + { + for (int32_t y = 0; y < h; ++y) + { ++ int32_t *cursampline = samptable + y * w; + int32_t prevsamp = 0; + for (int32_t x = 0; x < w; ++x) + { + int32_t nsamps = +- (int32_t) one_to_native32 ((uint32_t) samptable[y * w + x]); +- if (nsamps < 0) return EXR_ERR_INVALID_SAMPLE_DATA; +- samptable[y * w + x] = nsamps; +- prevsamp = nsamps; ++ (int32_t) one_to_native32 ((uint32_t) cursampline[x]); ++ if (nsamps < prevsamp) return EXR_ERR_INVALID_SAMPLE_DATA; ++ ++ cursampline[x] = nsamps; ++ prevsamp = nsamps; + } +- totsamp += prevsamp; ++ ++ totsamp += (uint64_t)prevsamp; + } + } + +- if (totsamp < 0 || +- (((uint64_t) totsamp) * combSampSize) > decode->chunk.unpacked_size) ++ if ((totsamp * combSampSize) > decode->chunk.unpacked_size) + { + rv = pctxt->report_error ( + pctxt, EXR_ERR_INVALID_SAMPLE_DATA, "Corrupt sample count table"); +diff --git a/src/lib/OpenEXRCore/unpack.c b/src/lib/OpenEXRCore/unpack.c +index b88c98974..1324508c5 100644 +--- a/src/lib/OpenEXRCore/unpack.c ++++ b/src/lib/OpenEXRCore/unpack.c +@@ -1196,9 +1196,10 @@ generic_unpack_deep_pointers (exr_decode_pipeline_t* decode) + if (outpix) + { + uint8_t* cdata = outpix; ++ + UNPACK_SAMPLES (samps) + } +- srcbuffer += bpc * samps; ++ srcbuffer += ((size_t) bpc) * ((size_t) samps); + } + } + sampbuffer += w; +@@ -1242,12 +1243,14 @@ generic_unpack_deep (exr_decode_pipeline_t* decode) + } + else + prevsamps = sampbuffer[w - 1]; ++ + srcbuffer += ((size_t) bpc) * ((size_t) prevsamps); + + if (incr_tot) totsamps += (size_t) prevsamps; + + continue; + } ++ + cdata += totsamps * ((size_t) ubpc); + + for (int x = 0; x < w; ++x) +@@ -1263,7 +1266,7 @@ generic_unpack_deep (exr_decode_pipeline_t* decode) + + UNPACK_SAMPLES (samps) + +- srcbuffer += bpc * samps; ++ srcbuffer += ((size_t) bpc) * ((size_t) samps); + if (incr_tot) totsamps += (size_t) samps; + } + } +@@ -1301,7 +1304,7 @@ internal_exr_match_decode ( + + if (isdeep) + { +- if ((decode->decode_flags & EXR_DECODE_SAMPLE_COUNTS_AS_INDIVIDUAL)) ++ if ((decode->decode_flags & EXR_DECODE_NON_IMAGE_DATA_AS_POINTERS)) + return &generic_unpack_deep_pointers; + return &generic_unpack_deep; + } +diff --git a/src/lib/OpenEXRUtil/ImfCheckFile.cpp b/src/lib/OpenEXRUtil/ImfCheckFile.cpp +index 82f318a92..4d45dad69 100644 +--- a/src/lib/OpenEXRUtil/ImfCheckFile.cpp ++++ b/src/lib/OpenEXRUtil/ImfCheckFile.cpp +@@ -1200,13 +1200,88 @@ runChecks (T& source, bool reduceMemory, bool reduceTime) + return threw; + } + ++// This is not entirely needed in that the chunk info has the ++// total unpacked_size field which can be used for allocation ++// but this adds an additional point to use when debugging issues. ++static exr_result_t ++realloc_deepdata(exr_decode_pipeline_t* decode) ++{ ++ int32_t w = decode->chunk.width; ++ int32_t h = decode->chunk.height; ++ uint64_t totsamps = 0, bytes = 0; ++ const int32_t *sampbuffer = decode->sample_count_table; ++ std::vector* ud = static_cast*>( ++ decode->decoding_user_data); ++ ++ if ( ! ud ) ++ { ++ for (int c = 0; c < decode->channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = decode->channels[c]; ++ outc.decode_to_ptr = NULL; ++ outc.user_pixel_stride = outc.user_bytes_per_element; ++ outc.user_line_stride = 0; ++ } ++ return EXR_ERR_SUCCESS; ++ } ++ ++ if ((decode->decode_flags & ++ EXR_DECODE_SAMPLE_COUNTS_AS_INDIVIDUAL)) ++ { ++ for (int32_t y = 0; y < h; ++y) ++ { ++ for (int x = 0; x < w; ++x) ++ totsamps += sampbuffer[x]; ++ sampbuffer += w; ++ } ++ } ++ else ++ { ++ for (int32_t y = 0; y < h; ++y) ++ totsamps += sampbuffer[y*w + w - 1]; ++ } ++ ++ for (int c = 0; c < decode->channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = decode->channels[c]; ++ bytes += totsamps * outc.user_bytes_per_element; ++ } ++ ++ if (bytes >= gMaxBytesPerDeepScanline * h) ++ { ++ for (int c = 0; c < decode->channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = decode->channels[c]; ++ outc.decode_to_ptr = NULL; ++ outc.user_pixel_stride = outc.user_bytes_per_element; ++ outc.user_line_stride = 0; ++ } ++ return EXR_ERR_SUCCESS; ++ } ++ ++ if (ud->size () < bytes) ++ ud->resize (bytes); ++ ++ uint8_t* dptr = &((*ud)[0]); ++ for (int c = 0; c < decode->channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = decode->channels[c]; ++ outc.decode_to_ptr = dptr; ++ outc.user_pixel_stride = outc.user_bytes_per_element; ++ outc.user_line_stride = 0; ++ ++ dptr += totsamps * (uint64_t) outc.user_bytes_per_element; ++ } ++ return EXR_ERR_SUCCESS; ++} ++ + //////////////////////////////////////// + + bool + readCoreScanlinePart ( + exr_context_t f, int part, bool reduceMemory, bool reduceTime) + { +- exr_result_t rv; ++ exr_result_t rv, frv; + exr_attr_box2i_t datawin; + rv = exr_get_data_window (f, part, &datawin); + if (rv != EXR_ERR_SUCCESS) return true; +@@ -1224,6 +1299,8 @@ readCoreScanlinePart ( + rv = exr_get_scanlines_per_chunk (f, part, &lines_per_chunk); + if (rv != EXR_ERR_SUCCESS) return true; + ++ frv = rv; ++ + for (uint64_t chunk = 0; chunk < height; chunk += lines_per_chunk) + { + exr_chunk_info_t cinfo = {0}; +@@ -1232,6 +1309,7 @@ readCoreScanlinePart ( + rv = exr_read_scanline_chunk_info (f, part, y, &cinfo); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) break; + continue; + } +@@ -1253,19 +1331,32 @@ readCoreScanlinePart ( + (uint64_t) lines_per_chunk; + } + +- // TODO: check we are supposed to multiple by lines per chunk above + doread = true; +- if (reduceMemory && bytes >= gMaxBytesPerScanline) doread = false; + +- if (doread) imgdata.resize (bytes); ++ if (cinfo.type == EXR_STORAGE_DEEP_SCANLINE) ++ { ++ decoder.decoding_user_data = &imgdata; ++ decoder.realloc_nonimage_data_fn = &realloc_deepdata; ++ } ++ else ++ { ++ if (reduceMemory && bytes >= gMaxBytesPerScanline) doread = false; ++ ++ if (doread) imgdata.resize (bytes); ++ } + rv = exr_decoding_choose_default_routines (f, part, &decoder); +- if (rv != EXR_ERR_SUCCESS) break; ++ if (rv != EXR_ERR_SUCCESS) ++ { ++ frv = rv; ++ break; ++ } + } + else + { + rv = exr_decoding_update (f, part, &cinfo, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) break; + continue; + } +@@ -1273,20 +1364,25 @@ readCoreScanlinePart ( + + if (doread) + { +- uint8_t* dptr = &(imgdata[0]); +- for (int c = 0; c < decoder.channel_count; c++) ++ if (cinfo.type != EXR_STORAGE_DEEP_SCANLINE) + { +- exr_coding_channel_info_t& outc = decoder.channels[c]; +- outc.decode_to_ptr = dptr; +- outc.user_pixel_stride = outc.user_bytes_per_element; +- outc.user_line_stride = outc.user_pixel_stride * width; +- dptr += width * (uint64_t) outc.user_bytes_per_element * ++ uint8_t* dptr = &(imgdata[0]); ++ for (int c = 0; c < decoder.channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = decoder.channels[c]; ++ outc.decode_to_ptr = dptr; ++ outc.user_pixel_stride = outc.user_bytes_per_element; ++ outc.user_line_stride = outc.user_pixel_stride * width; ++ ++ dptr += width * (uint64_t) outc.user_bytes_per_element * + (uint64_t) lines_per_chunk; ++ } + } + + rv = exr_decoding_run (f, part, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) break; + } + } +@@ -1294,7 +1390,7 @@ readCoreScanlinePart ( + + exr_decoding_destroy (f, &decoder); + +- return (rv != EXR_ERR_SUCCESS); ++ return (frv != EXR_ERR_SUCCESS); + } + + //////////////////////////////////////// +@@ -1303,7 +1399,7 @@ bool + readCoreTiledPart ( + exr_context_t f, int part, bool reduceMemory, bool reduceTime) + { +- exr_result_t rv; ++ exr_result_t rv, frv; + + exr_attr_box2i_t datawin; + rv = exr_get_data_window (f, part, &datawin); +@@ -1321,6 +1417,7 @@ readCoreTiledPart ( + rv = exr_get_tile_levels (f, part, &levelsx, &levelsy); + if (rv != EXR_ERR_SUCCESS) return true; + ++ frv = rv; + bool keepgoing = true; + for (int32_t ylevel = 0; keepgoing && ylevel < levelsy; ++ylevel) + { +@@ -1330,6 +1427,7 @@ readCoreTiledPart ( + rv = exr_get_level_sizes (f, part, xlevel, ylevel, &levw, &levh); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) + { + keepgoing = false; +@@ -1342,6 +1440,7 @@ readCoreTiledPart ( + rv = exr_get_tile_sizes (f, part, xlevel, ylevel, &curtw, &curth); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) + { + keepgoing = false; +@@ -1371,6 +1470,7 @@ readCoreTiledPart ( + f, part, tx, ty, xlevel, ylevel, &cinfo); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) + { + keepgoing = false; +@@ -1385,6 +1485,7 @@ readCoreTiledPart ( + exr_decoding_initialize (f, part, &cinfo, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + keepgoing = false; + break; + } +@@ -1406,14 +1507,23 @@ readCoreTiledPart ( + } + + doread = true; +- if (reduceMemory && bytes >= gMaxTileBytes) +- doread = false; ++ if (cinfo.type == EXR_STORAGE_DEEP_TILED) ++ { ++ decoder.decoding_user_data = &tiledata; ++ decoder.realloc_nonimage_data_fn = &realloc_deepdata; ++ } ++ else ++ { ++ if (reduceMemory && bytes >= gMaxTileBytes) ++ doread = false; + +- if (doread) tiledata.resize (bytes); ++ if (doread) tiledata.resize (bytes); ++ } + rv = exr_decoding_choose_default_routines ( + f, part, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + keepgoing = false; + break; + } +@@ -1423,6 +1533,7 @@ readCoreTiledPart ( + rv = exr_decoding_update (f, part, &cinfo, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) + { + keepgoing = false; +@@ -1434,24 +1545,28 @@ readCoreTiledPart ( + + if (doread) + { +- uint8_t* dptr = &(tiledata[0]); +- for (int c = 0; c < decoder.channel_count; c++) ++ if (cinfo.type != EXR_STORAGE_DEEP_TILED) + { +- exr_coding_channel_info_t& outc = +- decoder.channels[c]; +- outc.decode_to_ptr = dptr; +- outc.user_pixel_stride = +- outc.user_bytes_per_element; +- outc.user_line_stride = +- outc.user_pixel_stride * curtw; +- dptr += (uint64_t) curtw * ++ uint8_t* dptr = &(tiledata[0]); ++ for (int c = 0; c < decoder.channel_count; c++) ++ { ++ exr_coding_channel_info_t& outc = ++ decoder.channels[c]; ++ outc.decode_to_ptr = dptr; ++ outc.user_pixel_stride = ++ outc.user_bytes_per_element; ++ outc.user_line_stride = ++ outc.user_pixel_stride * curtw; ++ dptr += (uint64_t) curtw * + (uint64_t) outc.user_bytes_per_element * + (uint64_t) curth; ++ } + } + + rv = exr_decoding_run (f, part, &decoder); + if (rv != EXR_ERR_SUCCESS) + { ++ frv = rv; + if (reduceTime) + { + keepgoing = false; +@@ -1486,17 +1601,14 @@ checkCoreFile (exr_context_t f, bool reduceMemory, bool reduceTime) + rv = exr_get_storage (f, p, &store); + if (rv != EXR_ERR_SUCCESS) return true; + +- // TODO: Need to fill this in +- if (store == EXR_STORAGE_DEEP_SCANLINE || +- store == EXR_STORAGE_DEEP_TILED) +- continue; +- +- if (store == EXR_STORAGE_SCANLINE) ++ if (store == EXR_STORAGE_SCANLINE || ++ store == EXR_STORAGE_DEEP_SCANLINE) + { + if (readCoreScanlinePart (f, p, reduceMemory, reduceTime)) + return true; + } +- else if (store == EXR_STORAGE_TILED) ++ else if (store == EXR_STORAGE_TILED || ++ store == EXR_STORAGE_DEEP_TILED) + { + if (readCoreTiledPart (f, p, reduceMemory, reduceTime)) return true; + } + diff --git a/openexr.changes b/openexr.changes index c24cc8d..3e50cd3 100644 --- a/openexr.changes +++ b/openexr.changes @@ -1,3 +1,24 @@ +------------------------------------------------------------------- +Wed Feb 7 10:31:23 UTC 2024 - pgajdos@suse.com + +- version update to 3.2.1 + ## Version 3.2.0 (August 30, 2023) + * Zip compression via ``libdeflate`` + * New camdkit/camdkit-enabled standard attributes + * Updated SO versioning policy + * Python bindings & PyPI wheel + * Miscellaneous improvements + ## Version 3.2.1 (September 27, 2023) + * Fix for linking statically against an external ``libdeflate`` + * Fix a compile error with ``OPENEXR_VERSION_HEX`` + * Fix various compiler warnings + * Pkg-config generation is now on by default for all systems, including Windows +- modified sources + % baselibs.conf +- added patches + fix CVE-2023-5841 [bsc#1219498], heap-based buffer overflow in generic_unpack_deep() + + openexr-CVE-2023-5841.patch + ------------------------------------------------------------------- Thu Aug 24 13:21:39 UTC 2023 - pgajdos@suse.com diff --git a/openexr.spec b/openexr.spec index f27ff9a..195608a 100644 --- a/openexr.spec +++ b/openexr.spec @@ -1,7 +1,7 @@ # # spec file for package openexr # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,10 +19,10 @@ %define prjname openexr # perhaps you want to build against corresponding Imath build %define debug_build 0 -%define sonum 30 -%global so_suffix -3_1 +%define sonum 31 +%global so_suffix -3_2 Name: openexr -Version: 3.1.11 +Version: 3.2.1 Release: 0 Summary: Utilities for working with HDR images in OpenEXR format License: BSD-3-Clause @@ -30,11 +30,14 @@ Group: Development/Libraries/C and C++ URL: https://www.openexr.com/ Source0: https://github.com/openexr/openexr/archive/v%{version}.tar.gz Source2: baselibs.conf +# CVE-2023-5841 [bsc#1219498], heap-based buffer overflow in generic_unpack_deep() +Patch0: openexr-CVE-2023-5841.patch BuildRequires: cmake >= 3.12 BuildRequires: freeglut-devel BuildRequires: gcc-c++ BuildRequires: pkgconfig BuildRequires: pkgconfig(Imath) +BuildRequires: pkgconfig(libdeflate) BuildRequires: pkgconfig(zlib) Obsoletes: OpenEXR <= 1.6.1 Provides: OpenEXR = %{version} @@ -136,6 +139,7 @@ License: BSD-3-Clause Group: Documentation/Other Obsoletes: OpenEXR-doc <= 1.6.1 Provides: OpenEXR-doc = %{version} +BuildArch: noarch %description doc OpenEXR is a high dynamic-range (HDR) image file format developed by @@ -159,6 +163,16 @@ export CXXFLAGS="%{optflags} -O0" %cmake_install %check +# bin tests download test data from internet +EXCLUDE_REGEX='OpenEXR.bin' +%ifarch ppc64le +# bsc#1205885 +EXCLUDE_REGEX="$EXCLUDE_REGEX|testMultiTiledPartThreading" +%endif +%ifarch aarch64 +# https://github.com/AcademySoftwareFoundation/openexr/issues/1460 +EXCLUDE_REGEX="$EXCLUDE_REGEX|DWA[AB]Compression" +%endif # test failure on LE: https://github.com/AcademySoftwareFoundation/openexr/issues/1460 %ifnarch i586 ppc ppc64 s390 s390x export LD_LIBRARY_PATH="%{buildroot}/%{_libdir}" @@ -166,19 +180,9 @@ export LD_LIBRARY_PATH="%{buildroot}/%{_libdir}" %if 0%{?suse_version} < 1550 # HACK - older versions of the ctest macro do not allow passing additional parameters %global __ctest %{__ctest} --timeout 3600 -%ctest -%else -%ifarch ppc64le -# bsc#1205885 -EXCLUDE_REGEX='testMultiTiledPartThreading' -%endif -%ifarch aarch64 -# https://github.com/AcademySoftwareFoundation/openexr/issues/1460 -EXCLUDE_REGEX='DWA[AB]Compression' %endif %ctest --exclude-regex "$EXCLUDE_REGEX" --timeout 3600 %endif -%endif %post -n libIex%{so_suffix}-%{sonum} -p /sbin/ldconfig %postun -n libIex%{so_suffix}-%{sonum} -p /sbin/ldconfig diff --git a/v3.1.11.tar.gz b/v3.1.11.tar.gz deleted file mode 100644 index c1f6bba..0000000 --- a/v3.1.11.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:06b4a20d0791b5ec0f804c855d320a0615ce8445124f293616a086e093f1f1e1 -size 20539852 diff --git a/v3.2.1.tar.gz b/v3.2.1.tar.gz new file mode 100644 index 0000000..93d2ca6 --- /dev/null +++ b/v3.2.1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:61e175aa2203399fb3c8c2288752fbea3c2637680d50b6e306ea5f8ffdd46a9b +size 18824332