Compare commits

...
Sign in to create a new pull request.

15 commits

Author SHA1 Message Date
Benjamin A. Beasley
0d40a09f4d Rebuilt for materialx 1.39.5, which unexpectedly broke ABI
- Fixes RHBZ#2492227
2026-06-24 21:00:08 +01:00
Benjamin A. Beasley
5b067fcf44 Backport several OpenEXRCore security fixes
- Fixes CVE-2026-34378 / GHSA-v76p-4qvv-vh4g; closes RHBZ#2455493
- Fixes CVE-2026-34380 / GHSA-q3v8-hw4m-59w5; closes RHBZ#2455534
- Fixes CVE-2026-34588 / GHSA-588r-cr5c-w6hf; closes RHBZ#2455505
- Fixes CVE-2026-34589 / GHSA-p8xc-w3q4-h64x; closes RHBZ#2455501
- Fixes CVE-2026-34379 / GHSA-w88v-vqhq-5p24; closes RHBZ#2455497
2026-04-08 15:41:38 +01:00
Benjamin A. Beasley
5cfa713d7c Backport fix for CVE-2026-34544 in OpenEXRCore
- Fixes RHBZ#2454226
2026-04-07 14:21:17 +01:00
Orion Poplawski
9f0cb95186 Make devel require cmake(OpenSubdiv) and cmake(materialx) 2026-04-07 11:48:41 +01:00
Luya Tshimbalanga
0fbf7be4a4 Fix path for manterialx manual 2026-01-08 15:17:02 -08:00
Luya Tshimbalanga
19df409851 Fix manpage line 2026-01-08 09:10:12 -08:00
Luya Tshimbalanga
c42e9560b7 Enable materialx support 2026-01-08 08:16:29 -08:00
Luya Tshimbalanga
30f8fab770 Remove unused MaterialX support
This commit removed the unusued materialx support dropped by
upstream.
2026-01-07 19:00:11 -08:00
Benjamin A. Beasley
2bae199246 Backport fix for CVE-2025-14439/GHSA-grjp-54v3-c442 (fix RHBZ#2422276) 2025-12-24 13:51:47 +00:00
Benjamin A. Beasley
4b70806822 Backport fixes for CVE-2025-64181 etc. in OpenEXRCore 2025-12-02 19:40:46 +00:00
Jan Grulich
76dc694439 Rebuild (python-pyside6) 2025-12-02 15:51:30 +01:00
Benjamin A. Beasley
842d69ec9e Correct minimum NVR for stb_image 2025-11-25 14:32:28 +00:00
Benjamin A. Beasley
498e0bda2d Rebuilt with stb_image patched for two new security bugs 2025-11-25 14:21:51 +00:00
Benjamin A. Beasley
2b21748f53 Use macros for supported architectures
[skip changelog]
2025-11-25 14:21:51 +00:00
Benjamin A. Beasley
61ebf44868 Add direct build dependency on OpenCL as a workaround 2025-11-25 14:21:51 +00:00
5 changed files with 1550 additions and 12 deletions

View file

@ -0,0 +1,86 @@
From 63e1c9120a52766f7509dec4a312ced5cb15dd3f Mon Sep 17 00:00:00 2001
From: "Benjamin A. Beasley" <code@musicinmybrain.net>
Date: Tue, 2 Dec 2025 10:43:31 +0000
Subject: [PATCH] Backport fixes for CVE-2025-64181 etc. in OpenEXRCore
---
pxr/imaging/hio/OpenEXR/OpenEXRCore/chunk.c | 20 ++++++++++++++++---
.../hio/OpenEXR/OpenEXRCore/internal_util.h | 4 ++--
.../hio/OpenEXR/OpenEXRCore/parse_header.c | 4 +++-
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/chunk.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/chunk.c
index cfe80b4cd..e11209fe6 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/chunk.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/chunk.c
@@ -1292,6 +1292,16 @@ exr_read_tile_chunk_info (
return pctxt->report_error (
pctxt, EXR_ERR_INVALID_ARGUMENT, "Invalid packed size of 0");
+ if (part->comp_type == EXR_COMPRESSION_NONE &&
+ cinfo->packed_size != cinfo->unpacked_size)
+ {
+ return pctxt->print_error (
+ pctxt,
+ EXR_ERR_BAD_CHUNK_LEADER,
+ "Mismatch between unpacked and packed size with uncompressed data: packed is %" PRIu64 "; unpacked is %" PRIu64,
+ cinfo->packed_size, cinfo->unpacked_size);
+ }
+
return EXR_ERR_SUCCESS;
}
@@ -1350,11 +1360,15 @@ exr_read_chunk (
rv = pctxt->do_read (
pctxt, packed_data, toread, &dataoffset, &nread, rmode);
- if (rmode == EXR_ALLOW_SHORT_READ && nread < (int64_t) toread)
+ if (rmode == EXR_ALLOW_SHORT_READ &&
+ nread >= 0 &&
+ nread < (int64_t) toread)
+ {
memset (
((uint8_t*) packed_data) + nread,
- 0,
- toread - (uint64_t) (nread));
+ 0,
+ (size_t)(toread - (uint64_t)nread));
+ }
}
else
rv = EXR_ERR_SUCCESS;
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_util.h b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_util.h
index 3c6f02786..e0fa3933d 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_util.h
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_util.h
@@ -31,10 +31,10 @@ compute_sampled_height (int height, int y_sampling, int start_y)
else
start = start_y;
end = start_y + height - 1;
- end -= (end < 0) ? (-end % y_sampling) : (end % y_sampling);
+ end -= (end < 0 ? -end : end) % y_sampling;
if (start > end)
- nlines = 0;
+ nlines = start == start_y ? 1 : 0;
else
nlines = (end - start) / y_sampling + 1;
}
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/parse_header.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/parse_header.c
index d72303926..8b6cf78cc 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/parse_header.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/parse_header.c
@@ -2293,7 +2293,9 @@ internal_exr_compute_chunk_offset_size (struct _internal_exr_part* curpart)
w = (uint64_t) (((int64_t) dw.max.x) - ((int64_t) dw.min.x) + 1);
- if (curpart->tiles)
+ if (curpart->storage_mode != EXR_STORAGE_SCANLINE &&
+ curpart->storage_mode != EXR_STORAGE_DEEP_SCANLINE &&
+ curpart->tiles)
{
const exr_attr_tiledesc_t* tiledesc = curpart->tiles->tiledesc;
int64_t tilecount = 0;
--
2.52.0

View file

@ -0,0 +1,74 @@
From ae97658675f83466d13149178ccfad95731c3ed2 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Thu, 19 Mar 2026 14:22:40 -0700
Subject: [PATCH] Fix B44/B44A integer overflow: use uint64_t for row offset
(#2312)
The B44 and B44A decoder and encoder use channel width (`nx`) and
height (`ny`) in row pointer math. `nx` and `ny` are `int`; the
scratch buffer is correctly sized with `(uint64_t)ny * (uint64_t)nx *
bytes_per_element`, but row bases were computed as:
```
row0 = (uint16_t*)scratch;
row0 += y * nx; // int * int -> signed overflow when y*nx > INT_MAX
```
For large `nx` (e.g. 268435456), `y*nx` overflows, so `row0`/`row1`/`row2`/`row3`
point before the scratch buffer.
Fix: compute the row offset in `uint64_t` before pointer arithmetic in both
`uncompress_b44_impl` (decoder) and `compress_b44_impl` (encoder).
Analysis and solution with the help of Curor / Claude Opus 4.5
Signed-off-by: Cary Phillips <cary@ilm.com>
---
.../hio/OpenEXR/OpenEXRCore/internal_b44.c | 23 ++++++++++---------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_b44.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_b44.c
index 8d0c257e6..93279ff2e 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_b44.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_b44.c
@@ -390,13 +390,13 @@ compress_b44_impl (exr_encode_pipeline_t* encode, int flat_field)
// rightmost column and the bottom row.
//
uint16_t *row0, *row1, *row2, *row3;
+ /* row offset in elements: use uint64_t so y*nx cannot overflow int */
+ uint64_t row_off = (uint64_t) (y) * (uint64_t) (nx);
- row0 = (uint16_t*) scratch;
- row0 += y * nx;
-
- row1 = row0 + nx;
- row2 = row1 + nx;
- row3 = row2 + nx;
+ row0 = (uint16_t*) scratch + row_off;
+ row1 = row0 + (uint64_t) nx;
+ row2 = row1 + (uint64_t) nx;
+ row3 = row2 + (uint64_t) nx;
if (y + 3 >= ny)
{
@@ -512,11 +512,12 @@ uncompress_b44_impl (
for (int y = 0; y < ny; y += 4)
{
- row0 = (uint16_t*) scratch;
- row0 += y * nx;
- row1 = row0 + nx;
- row2 = row1 + nx;
- row3 = row2 + nx;
+ /* row offset in elements: use uint64_t so y*nx cannot overflow int */
+ uint64_t row_off = (uint64_t) (y) * (uint64_t) (nx);
+ row0 = (uint16_t*) scratch + row_off;
+ row1 = row0 + (uint64_t) nx;
+ row2 = row1 + (uint64_t) nx;
+ row3 = row2 + (uint64_t) nx;
for (int x = 0; x < nx; x += 4)
{
if (bIn + 3 > comp_buf_size) return EXR_ERR_OUT_OF_MEMORY;
--
2.53.0

View file

@ -0,0 +1,686 @@
From 5c609492c6c01bbd5fe57c73cb88d279d9195c29 Mon Sep 17 00:00:00 2001
From: sunyab <sunyab@users.noreply.github.com>
Date: Fri, 26 Sep 2025 13:16:55 -0700
Subject: [PATCH] sdf: Guard against invalid primChildren in crate files
A crate file containing a primChildren field on a prim with invalid
entries (e.g. an empty name or name with invalid characters)
could lead to issues when accessing that prim's children later
on. In addition, duplicate entries in the field could cause
unexpected behavior when iterating over those children.
We now check for these conditions when loading a crate file and
emit a runtime error and fail to load the layer if we encounter
this problem.
This situation typically does not occur via regular Sdf and
Usd usage, so we only do this verification if
PXR_PREFER_SAFETY_OVER_SPEED is enabled.
(Internal change: 2380262)
(Internal change: 2380126)
---
pxr/usd/sdf/CMakeLists.txt | 19 +++
pxr/usd/sdf/crateData.cpp | 127 +++++++++++++++++-
.../testSdfUsdcInvalidPrimChildren.cpp | 84 ++++++++++++
.../duplicate_prim_children.usdc | Bin 0 -> 704 bytes
.../root.usdc | Bin 0 -> 38110 bytes
5 files changed, 227 insertions(+), 3 deletions(-)
create mode 100644 pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.cpp
create mode 100644 pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/duplicate_prim_children.usdc
create mode 100644 pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/root.usdc
diff --git a/pxr/usd/sdf/CMakeLists.txt b/pxr/usd/sdf/CMakeLists.txt
index 092422acb..38bc4c4d2 100644
--- a/pxr/usd/sdf/CMakeLists.txt
+++ b/pxr/usd/sdf/CMakeLists.txt
@@ -412,6 +412,16 @@ pxr_build_test(testSdfZipFile_CPP
testenv/testSdfZipFile.cpp
)
+pxr_build_test(testSdfUsdcInvalidPrimChildren
+ LIBRARIES
+ ar
+ arch
+ tf
+ sdf
+ CPPFILES
+ testenv/testSdfUsdcInvalidPrimChildren.cpp
+)
+
pxr_install_test_dir(
SRC testenv/testSdfBatchNamespaceEdit.testenv
DEST testSdfBatchNamespaceEdit/testSdfBatchNamespaceEdit.testenv
@@ -461,6 +471,11 @@ pxr_install_test_dir(
SRC testenv/testSdfUsdzResolver
DEST testSdfUsdzResolver
)
+
+pxr_install_test_dir(
+ SRC testenv/testSdfUsdcInvalidPrimChildren.testenv
+ DEST testSdfUsdcInvalidPrimChildren
+)
pxr_register_test(testSdfAbstractData_Cpp
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testSdfAbstractData_Cpp"
@@ -704,3 +719,7 @@ pxr_register_test(testSdfVariants
PYTHON
COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testSdfVariants"
)
+pxr_register_test(testSdfUsdcInvalidPrimChildren
+ COMMAND "${CMAKE_INSTALL_PREFIX}/tests/testSdfUsdcInvalidPrimChildren"
+ EXPECTED_RETURN_CODE 0
+)
diff --git a/pxr/usd/sdf/crateData.cpp b/pxr/usd/sdf/crateData.cpp
index 8fe924779..820418128 100644
--- a/pxr/usd/sdf/crateData.cpp
+++ b/pxr/usd/sdf/crateData.cpp
@@ -17,6 +17,7 @@
#include "pxr/base/tf/stringUtils.h"
#include "pxr/base/tf/typeInfoMap.h"
#include "pxr/base/tf/pxrTslRobinMap/robin_map.h"
+#include "pxr/base/tf/pxrTslRobinMap/robin_set.h"
#include "pxr/base/trace/trace.h"
#include "pxr/base/work/dispatcher.h"
@@ -29,6 +30,8 @@
#include <tbb/parallel_for.h>
#include <tbb/parallel_sort.h>
+#include <tbb/blocked_range.h>
+#include <tbb/concurrent_vector.h>
#include <algorithm>
#include <functional>
@@ -717,6 +720,7 @@ public:
////////////////////////////////////////////////////////////////////////
private:
+ using TokenSet = pxr_tsl::robin_set<TfToken, TfToken::HashFunctor>;
bool _PopulateFromCrateFile() {
@@ -815,10 +819,11 @@ private:
}
// Create all the specData entries and store pointers to them.
- tbb::parallel_for(
- tbb::blocked_range<size_t>(0, specs.size()),
+ auto createSpecData =
[this, crateFile, &liveFieldSets, &specs](
- tbb::blocked_range<size_t> const &r) {
+ tbb::blocked_range<size_t> const &r,
+ auto&& validateChildrenFn) {
+
for (size_t i = r.begin(),
end = r.end(); i != end; ++i) {
@@ -830,10 +835,59 @@ private:
specData.fields =
liveFieldSets.find(spec.fieldSetIndex)->second;
+ std::forward<decltype(validateChildrenFn)>
+ (validateChildrenFn)(spec, specData);
+ }
+ };
+
+#ifndef PXR_PREFER_SAFETY_OVER_SPEED
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, specs.size()),
+ [&createSpecData](tbb::blocked_range<size_t> const& r) {
+ createSpecData(r, [](auto&&...) {});
+ });
+#else
+ // In safety-over-speed mode we perform additional validation
+ // on specs in worker threads. We need to collect runtime errors
+ // emitted in those threads and transport them back to the
+ // original thread.
+ tbb::concurrent_vector<TfErrorTransport> errorTransports;
+
+ tbb::parallel_for(
+ tbb::blocked_range<size_t>(0, specs.size()),
+ [this, &createSpecData, &errorTransports](
+ tbb::blocked_range<size_t> const& r) {
+
+ // Reuse a TokenSet for duplicate checking in
+ // _ValidateSpecChildren to avoid allocating memory
+ // repeatedly.
+ TokenSet dupeTokenSet;
+ TfErrorMark m;
+
+ createSpecData(
+ r,
+ [this, &dupeTokenSet](auto&&... args) {
+ _ValidateSpecChildren(
+ std::forward<decltype(args)>(args)...,
+ &dupeTokenSet);
+ });
+
+ if (!m.IsClean()) {
+ TfErrorTransport transport = m.Transport();
+ errorTransports.grow_by(1)->swap(transport);
}
},
tbb::static_partitioner());
+ for (TfErrorTransport& transport : errorTransports) {
+ transport.Post();
+ }
+
+ if (!m.IsClean()) {
+ return false;
+ }
+#endif
+
_lastSet = _data.end();
return true;
@@ -851,6 +905,73 @@ private:
return ret;
}
+ inline bool _HasValidChildren(const SdfPath &path,
+ const VtValue &val,
+ TokenSet* dupeTokenSet) const {
+ if (!val.IsHolding<TfTokenVector>()) {
+ return false;
+ }
+
+ enum class ErrorType { Invalid, Duplicate };
+ ErrorType errorType;
+ dupeTokenSet->clear();
+
+ const TfTokenVector& children = val.UncheckedGet<TfTokenVector>();
+ auto invalidChild = std::find_if(children.begin(), children.end(),
+ [&](const TfToken& childName) {
+ // Check that the child has a valid identifier and that the
+ // child path exists in the data.
+ if (!SdfPath::IsValidIdentifier(childName) ||
+ _data.find(path.AppendChild(childName)) == _data.end()) {
+ errorType = ErrorType::Invalid;
+ return true;
+ }
+
+ // Check that the child does not duplicate another child.
+ if (!dupeTokenSet->insert(childName).second) {
+ errorType = ErrorType::Duplicate;
+ return true;
+ }
+
+ return false;
+ });
+ if (ARCH_UNLIKELY(invalidChild != children.end())) {
+ TF_RUNTIME_ERROR(
+ "%s child identifier '%s' found on parent '%s'",
+ (errorType == ErrorType::Duplicate ?
+ "Duplicate" : "Invalid"),
+ invalidChild->GetText(), path.GetAsString().c_str());
+ return false;
+ }
+
+ return true;
+ }
+
+ inline bool _ValidateSpecChildren(const CrateFile::Spec& spec,
+ const _SpecData &specData,
+ TokenSet* dupeTokenSet) const {
+ if (specData.specType == SdfSpecTypePrim) {
+ // Check for invalid children in primChildren field
+ _FieldValuePairVector const &fields = specData.fields.Get();
+ auto field = std::find_if(fields.begin(), fields.end(),
+ [](_FieldValuePair const &fieldValue) {
+ return fieldValue.first == SdfChildrenKeys->PrimChildren;
+ });
+ if (field != fields.end()) {
+ SdfPath const &path = _crateFile->GetPath(spec.pathIndex);
+ VtValue const &value = field->second;
+ if (!_HasValidChildren(path, value, dupeTokenSet)) {
+ TF_RUNTIME_ERROR(
+ "Invalid children found in primChildren field for path "
+ "'%s'", path.GetAsString().c_str());
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
inline std::vector<double> const &
_ListTimeSamplesForPath(const SdfPath &path) const {
TF_DESCRIBE_SCOPE(GetAssetPath().c_str());
diff --git a/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.cpp b/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.cpp
new file mode 100644
index 000000000..49258b657
--- /dev/null
+++ b/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright 2025 Pixar
+//
+// Licensed under the terms set forth in the LICENSE.txt file available at
+// https://openusd.org/license.
+//
+
+#include "pxr/pxr.h"
+
+#include "pxr/base/tf/error.h"
+#include "pxr/base/tf/errorMark.h"
+#include "pxr/base/tf/diagnosticLite.h"
+#include "pxr/usd/sdf/childrenView.h"
+#include "pxr/usd/sdf/layer.h"
+#include "pxr/usd/sdf/primSpec.h"
+
+#include <string>
+#include <cstring>
+
+PXR_NAMESPACE_USING_DIRECTIVE
+
+static void
+TestInvalidPrimChildren()
+{
+ // This test relies on verification checks that are only enabled when
+ // PXR_PREFER_SAFETY_OVER_SPEED is enabled.
+#ifdef PXR_PREFER_SAFETY_OVER_SPEED
+ // open the layer and check for invalid child prim names and specs
+ TfErrorMark m;
+
+ auto layer = SdfLayer::FindOrOpen("root.usdc");
+ TF_AXIOM(!layer);
+
+ TF_AXIOM(!m.IsClean());
+ TF_AXIOM(std::any_of(m.begin(), m.end(),
+ [](const TfError& e) {
+ return TfStringEndsWith(e.GetCommentary(),
+ "Invalid child identifier '' found "
+ "on parent '/_materials'");
+ }));
+ TF_AXIOM(std::any_of(m.begin(), m.end(),
+ [](const TfError& e) {
+ return TfStringEndsWith(e.GetCommentary(),
+ "Invalid children found in primChildren field "
+ "for path '/_materials'");
+ }));
+#endif
+}
+
+static void
+TestDuplicatePrimChildren()
+{
+ // This test relies on verification checks that are only enabled when
+ // PXR_PREFER_SAFETY_OVER_SPEED is enabled.
+#ifdef PXR_PREFER_SAFETY_OVER_SPEED
+ // open the layer and check for invalid child prim names and specs
+ TfErrorMark m;
+
+ auto layer = SdfLayer::FindOrOpen("duplicate_prim_children.usdc");
+ TF_AXIOM(!layer);
+
+ TF_AXIOM(!m.IsClean());
+ TF_AXIOM(std::any_of(m.begin(), m.end(),
+ [](const TfError& e) {
+ return TfStringEndsWith(e.GetCommentary(),
+ "Duplicate child identifier 'Child1' found "
+ "on parent '/Root'");
+ }));
+ TF_AXIOM(std::any_of(m.begin(), m.end(),
+ [](const TfError& e) {
+ return TfStringEndsWith(e.GetCommentary(),
+ "Invalid children found in primChildren field "
+ "for path '/Root'");
+ }));
+#endif
+}
+
+int main(int argc, char** argv)
+{
+ TestInvalidPrimChildren();
+ TestDuplicatePrimChildren();
+
+ return 0;
+}
diff --git a/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/duplicate_prim_children.usdc b/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/duplicate_prim_children.usdc
new file mode 100644
index 0000000000000000000000000000000000000000..b6710e961deb11804a49dbaf2fd2ceb31d261d65
GIT binary patch
literal 704
zcmbu7&rZTX5XQf4sV$-j!K(+Z97z0gG*L-eg+OXUYvNH1O(X%@)SBRpgAc$1_y8Wg
z`Zhj-9!yNcVismBoSn-zncwWUJJY&Xo$94mw_#xsUt+2M4Ytt$=wy}yU;x+v*0`#x
zSmi2b4--IvdfKE7QhZoP)e6uF!vs;>AKJJ5K`#zQ$fLAxqI6*5ediF}B#9BlVHCtk
zKe$6LyuTR)NFJiV=?(*S`+LhKS0?JkQirz7mGT$@dlfvIuu;L2g-L$F3a3j2iro9A
z5?_kBmg+ybnVMV$D^G=~nzbgNr|TtGXrEi#bP6wOlhT-DrloAbS0YjtBHI+EYWKnb
zMCPfSjGQ_D=HvcFOFAB306bHAP3rlbrgNS(SoBfocfnaxw(A*2k@zv4UvlYli$lCj
X+^zWyW-3O+Tf{wA+N=DP_zCe}Iz2v9
literal 0
HcmV?d00001
diff --git a/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/root.usdc b/pxr/usd/sdf/testenv/testSdfUsdcInvalidPrimChildren.testenv/root.usdc
new file mode 100644
index 0000000000000000000000000000000000000000..651668dd7b6012b65e8fde4bfb4a973a697ceb58
GIT binary patch
literal 38110
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
C@)ZIA
literal 0
HcmV?d00001
--
2.52.0

630
usd-25.08-pr-4030.patch Normal file
View file

@ -0,0 +1,630 @@
From e3c7f7bdf877aae4961a6d6f38f14ae7e3484640 Mon Sep 17 00:00:00 2001
From: Christoph Gohlke <cgohlke@cgohlke.com>
Date: Tue, 17 Mar 2026 20:56:39 -0700
Subject: [PATCH 1/6] Fix comparison operator for buffer size check (#2307)
Signed-off-by: Christoph Gohlke <cgohlke@cgohlke.com>
---
pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_zip.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_zip.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_zip.c
index 628438c5c..56df6a49c 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_zip.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_zip.c
@@ -367,7 +367,7 @@ apply_zip_impl (exr_encode_pipeline_t* encode)
if (rv == EXR_ERR_SUCCESS)
{
- if (compbufsz > encode->packed_bytes)
+ if (compbufsz >= encode->packed_bytes)
{
memcpy (
encode->compressed_buffer,
--
2.53.0
From 2d415fb1a62e8c951e3c515a3cb46bda7cc60749 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Thu, 26 Mar 2026 16:35:49 -0700
Subject: [PATCH 2/6] Fix integer overflow in `srcbuffer` pointer arithmetic in
`unpack_*` (#2321)
Pointer arithmetic involving `srcbuffer` in the `unpack_*` functions
can overflow for very wide images.
Multiplying `int w` by a bytes-per-element constant (2, 4, 6, or 8) in
`srcbuffer +=` expressions causes signed integer overflow when the
image width is large.
Promote the leading operand to `int64_t` at every affected multiplication
so pointer arithmetic is performed in 64-bit signed arithmetic throughout,
eliminating the undefined behavior without imposing any image size limit.
Affected sites: `generic_unpack`, `unpack_16bit`, `unpack_32bit`, and
all 3- and 4-channel interleave/planar specializations.
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
---
pxr/imaging/hio/OpenEXR/OpenEXRCore/unpack.c | 38 ++++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/unpack.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/unpack.c
index b88c98974..a311f9129 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/unpack.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/unpack.c
@@ -229,7 +229,7 @@ unpack_16bit_3chan_interleave (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = one_to_native16 (in0[x]);
@@ -269,7 +269,7 @@ unpack_16bit_3chan_interleave_rev (exr_decode_pipeline_t* decode)
in1 = in0 + w; // G
in2 = in1 + w; // R
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = one_to_native16 (in2[x]);
@@ -309,7 +309,7 @@ unpack_half_to_float_3chan_interleave (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = half_to_float (one_to_native16 (in0[x]));
@@ -349,7 +349,7 @@ unpack_half_to_float_3chan_interleave_rev (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = half_to_float (one_to_native16 (in2[x]));
@@ -390,7 +390,7 @@ unpack_16bit_3chan_planar (exr_decode_pipeline_t* decode)
in0 = (const uint16_t*) srcbuffer;
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
/* specialise to memcpy if we can */
#if EXR_HOST_IS_NOT_LITTLE_ENDIAN
for (int x = 0; x < w; ++x)
@@ -440,7 +440,7 @@ unpack_half_to_float_3chan_planar (exr_decode_pipeline_t* decode)
in0 = (const uint16_t*) srcbuffer;
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
/* specialise to memcpy if we can */
half_to_float_buffer ((float*) out0, in0, w);
half_to_float_buffer ((float*) out1, in1, w);
@@ -485,7 +485,7 @@ unpack_16bit_3chan (exr_decode_pipeline_t* decode)
in0 = (const uint16_t*) srcbuffer;
in1 = in0 + w;
in2 = in1 + w;
- srcbuffer += w * 6; // 3 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 6; // 3 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
*((uint16_t*) (out0 + x * inc0)) = one_to_native16 (in0[x]);
for (int x = 0; x < w; ++x)
@@ -539,7 +539,7 @@ unpack_16bit_4chan_interleave (exr_decode_pipeline_t* decode)
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
combined.a = one_to_native16 (in0[x]);
@@ -592,7 +592,7 @@ unpack_16bit_4chan_interleave_rev (exr_decode_pipeline_t* decode)
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
combined.a = one_to_native16 (in0[x]);
@@ -633,7 +633,7 @@ unpack_half_to_float_4chan_interleave (exr_decode_pipeline_t* decode)
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = half_to_float (one_to_native16 (in3[x]));
@@ -674,7 +674,7 @@ unpack_half_to_float_4chan_interleave_rev (exr_decode_pipeline_t* decode)
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
{
out[0] = half_to_float (one_to_native16 (in0[x]));
@@ -719,7 +719,7 @@ unpack_16bit_4chan_planar (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
/* specialize to memcpy if we can */
#if EXR_HOST_IS_NOT_LITTLE_ENDIAN
for (int x = 0; x < w; ++x)
@@ -775,7 +775,7 @@ unpack_half_to_float_4chan_planar (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
half_to_float_buffer ((float*) out0, in0, w);
half_to_float_buffer ((float*) out1, in1, w);
@@ -825,7 +825,7 @@ unpack_16bit_4chan (exr_decode_pipeline_t* decode)
in1 = in0 + w;
in2 = in1 + w;
in3 = in2 + w;
- srcbuffer += w * 8; // 4 * sizeof(uint16_t), avoid type conversion
+ srcbuffer += (int64_t) w * 8; // 4 * sizeof(uint16_t), avoid type conversion
for (int x = 0; x < w; ++x)
*((uint16_t*) (out0 + x * inc0)) = one_to_native16 (in0[x]);
for (int x = 0; x < w; ++x)
@@ -898,7 +898,7 @@ unpack_16bit (exr_decode_pipeline_t* decode)
}
}
#endif
- srcbuffer += w * 2;
+ srcbuffer += (int64_t) w * 2;
}
}
return EXR_ERR_SUCCESS;
@@ -963,7 +963,7 @@ unpack_32bit (exr_decode_pipeline_t* decode)
}
}
#endif
- srcbuffer += w * 4;
+ srcbuffer += (int64_t) w * 4;
}
}
return EXR_ERR_SUCCESS;
@@ -1118,7 +1118,7 @@ generic_unpack (exr_decode_pipeline_t* decode)
(uint64_t) decc->user_line_stride);
else
{
- srcbuffer += w * bpc;
+ srcbuffer += (int64_t) w * bpc;
continue;
}
}
@@ -1128,12 +1128,12 @@ generic_unpack (exr_decode_pipeline_t* decode)
}
else
{
- srcbuffer += w * bpc;
+ srcbuffer += (int64_t) w * bpc;
continue;
}
UNPACK_SAMPLES (w)
- srcbuffer += w * bpc;
+ srcbuffer += (int64_t) w * bpc;
}
}
return EXR_ERR_SUCCESS;
--
2.53.0
From b76c840e5c0b7a99e25c02e2ced420b4a8af0896 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Sun, 29 Mar 2026 19:19:12 -0700
Subject: [PATCH 3/6] Security: fix signed integer overflow in
`undo_pxr24_impl()` (PXR24 decoder) (#2323)
In the `EXR_PIXEL_FLOAT` branch of `undo_pxr24_impl()`, the expressions
(uint64_t)(w * 3)
compute the signed 32-bit product `w * 3` before the cast to `uint64_t`.
When `w` is large this is undefined behavior under the C standard; on
two's-complement builds without sanitizers the result wraps to a small
positive value, which can cause the bounds check
if (nDec + (uint64_t)(w * 3) > outSize)
to pass incorrectly. If the check is bypassed the decode loop proceeds
to write `4*w` bytes through `dout`, potentially far beyond the allocated
output buffer.
Fix: cast `w` to `uint64_t` before multiplying so that both the bounds
check and the counter update are performed entirely in 64-bit unsigned
arithmetic:
(uint64_t)w * 3 (cast before multiply, not after)
The `EXR_PIXEL_UINT` and `EXR_PIXEL_HALF` decode branches are unaffected:
they reuse the pre-computed `nBytes` variable, which is already formed as
`(uint64_t)(w) * (uint64_t)(bytes_per_element)`.
Also fix the symmetric issue in `apply_pxr24_impl()` (the encoder):
lastIn += w * 4
advances a pointer by a signed 32-bit product; corrected to
lastIn += (uint64_t)w * 4
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
---
pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_pxr24.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_pxr24.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_pxr24.c
index 43e52c982..30f71f4f8 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_pxr24.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_pxr24.c
@@ -182,7 +182,7 @@ apply_pxr24_impl (exr_encode_pipeline_t* encode)
if (nOut + nBytes > encode->scratch_alloc_size_1)
return EXR_ERR_OUT_OF_MEMORY;
nOut += nBytes;
- lastIn += w * 4;
+ lastIn += (uint64_t) w * 4;
ptr[0] = out;
out += w;
@@ -371,7 +371,7 @@ undo_pxr24_impl (
ptr[2] = lastIn;
lastIn += w;
- if (nDec + (uint64_t) (w * 3) > outSize)
+ if (nDec + (uint64_t) w * 3 > outSize)
return EXR_ERR_CORRUPT_CHUNK;
for (int x = 0; x < w; ++x)
@@ -384,7 +384,7 @@ undo_pxr24_impl (
unaligned_store32 (dout, pixel);
++dout;
}
- nDec += (uint64_t) (w * 3);
+ nDec += (uint64_t) w * 3;
break;
}
default: return EXR_ERR_INVALID_ARGUMENT;
--
2.53.0
From 72af902014ba12d414f31b585175723bc7e62cd2 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Sun, 29 Mar 2026 19:19:49 -0700
Subject: [PATCH 4/6] fix integer overflow in PIZ wavelet buffer arithmetic
(#2328)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Three classes of signed integer overflow in the PIZ codec path, all
reachable from corrupt `dataWindow` dimensions in the EXR file header.
**`wav_2D_encode` / `wav_2D_decode` — wavelet loop pointer arithmetic**
`oy` is passed as `int` (value `wcount * nx`, at most ~INT32_MAX after
the guard below). Inside the hierarchical wavelet loop the expressions
ey = in + oy * (ny - p2) // pointer end-of-row sentinel
oy1 = oy * p // row stride at level p
oy2 = oy * p2 // row stride at level p2
multiply two values that can each approach INT32_MAX, producing a
signed 32-bit product that wraps to a small or negative value. The
wrapped value is used as a pointer offset, causing reads and writes
through `px` / `py` to land outside the allocated wavelet buffer.
Fix: widen by introducing `int64_t oy64 = oy` and using it for all
three expressions; `oy1` and `oy2` are also declared `int64_t`.
**`wavbuf += nx * ny * wcount` — per-channel buffer advance**
`nx`, `ny`, and `wcount` are all `int`. Their triple product overflows
int32 for moderately large images, causing subsequent channels to be
processed at an incorrect (too-small) offset into the wavelet buffer,
corrupting both encode and decode output.
Fix: cast to `(uint64_t)` before multiplying.
**`wcount * nx` — call-site argument overflow**
The fifth argument to `wav_2D_encode` / `wav_2D_decode` is `wcount * nx`
(`oy` = y-stride = elements per row). `wcount` is 1 or 2
(`bytes_per_element / 2`); for `wcount = 2` the product overflows int32
when `nx > INT32_MAX / 2`.
Fix: add an early bounds check `if (wcount > 0 && nx > INT_MAX / wcount)`
that rejects such input as `EXR_ERR_CORRUPT_CHUNK` before any arithmetic
is performed. This also keeps `wcount * nx` within int32 range at the
call site, ensuring `oy` arrives in the wavelet functions with a valid
non-overflowed value.
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
---
.../hio/OpenEXR/OpenEXRCore/internal_piz.c | 39 +++++++++++--------
1 file changed, 23 insertions(+), 16 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_piz.c b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_piz.c
index 6c2750b16..787d2752c 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_piz.c
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_piz.c
@@ -10,6 +10,7 @@
#include "internal_huf.h"
#include "internal_xdr.h"
+#include <limits.h>
#include <string.h>
/**************************************/
@@ -171,10 +172,11 @@ wdec16 (uint16_t l, uint16_t h, uint16_t* a, uint16_t* b)
static void
wav_2D_encode (uint16_t* in, int nx, int ox, int ny, int oy, uint16_t mx)
{
- int w14 = (mx < (1 << 14)) ? 1 : 0;
- int n = (nx > ny) ? ny : nx;
- int p = 1; // == 1 << level
- int p2 = 2; // == 1 << (level+1)
+ int w14 = (mx < (1 << 14)) ? 1 : 0;
+ int n = (nx > ny) ? ny : nx;
+ int p = 1; // == 1 << level
+ int p2 = 2; // == 1 << (level+1)
+ int64_t oy64 = oy;
//
// Hierarchical loop on smaller dimension n
@@ -183,9 +185,9 @@ wav_2D_encode (uint16_t* in, int nx, int ox, int ny, int oy, uint16_t mx)
while (p2 <= n)
{
uint16_t* py = in;
- uint16_t* ey = in + oy * (ny - p2);
- int oy1 = oy * p;
- int oy2 = oy * p2;
+ uint16_t* ey = in + oy64 * (ny - p2);
+ int64_t oy1 = oy64 * p;
+ int64_t oy2 = oy64 * p2;
int ox1 = ox * p;
int ox2 = ox * p2;
uint16_t i00, i01, i10, i11;
@@ -284,10 +286,11 @@ wav_2D_decode (
int oy, // i : y offset
uint16_t mx) // i : maximum in[x][y] value
{
- int w14 = (mx < (1 << 14)) ? 1 : 0;
- int n = (nx > ny) ? ny : nx;
- int p = 1;
- int p2;
+ int w14 = (mx < (1 << 14)) ? 1 : 0;
+ int n = (nx > ny) ? ny : nx;
+ int p = 1;
+ int p2;
+ int64_t oy64 = oy;
//
// Search max level
@@ -307,9 +310,9 @@ wav_2D_decode (
while (p >= 1)
{
uint16_t* py = in;
- uint16_t* ey = in + oy * (ny - p2);
- int oy1 = oy * p;
- int oy2 = oy * p2;
+ uint16_t* ey = in + oy64 * (ny - p2);
+ int64_t oy1 = oy64 * p;
+ int64_t oy2 = oy64 * p2;
int ox1 = ox * p;
int ox2 = ox * p2;
uint16_t i00, i01, i10, i11;
@@ -502,11 +505,13 @@ internal_exr_apply_piz (exr_encode_pipeline_t* encode)
nx = curc->width;
ny = curc->height;
wcount = (int) (curc->bytes_per_element / 2);
+ if (wcount > 0 && nx > INT_MAX / wcount)
+ return EXR_ERR_CORRUPT_CHUNK;
for (int j = 0; j < wcount; ++j)
{
wav_2D_encode (wavbuf + j, nx, wcount, ny, wcount * nx, maxValue);
}
- wavbuf += nx * ny * wcount;
+ wavbuf += (uint64_t) nx * ny * wcount;
}
nBytes = 0;
@@ -655,11 +660,13 @@ internal_exr_undo_piz (
nx = curc->width;
ny = curc->height;
wcount = (int) (curc->bytes_per_element / 2);
+ if (wcount > 0 && nx > INT_MAX / wcount)
+ return EXR_ERR_CORRUPT_CHUNK;
for (int j = 0; j < wcount; ++j)
{
wav_2D_decode (wavbuf + j, nx, wcount, ny, wcount * nx, maxValue);
}
- wavbuf += nx * ny * wcount;
+ wavbuf += (uint64_t) nx * ny * wcount;
}
//
--
2.53.0
From 7d3eb08f2322d199a874602e961d63004a145650 Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Sun, 29 Mar 2026 19:20:52 -0700
Subject: [PATCH 5/6] Fix signed integer overflow in
`LossyDctDecoder_execute()` pointer arithmetic (#2329)
`numBlocksX` and `numBlocksY` are declared as `int`. Two pointer-offset
expressions in `LossyDctDecoder_execute()` multiplied them as signed
32-bit integers before using the result as a pointer offset:
rowBlock[comp] = rowBlock[comp - 1] + numBlocksX * 64;
currDcComp[comp] = currDcComp[comp - 1] + numBlocksX * numBlocksY;
`dataWindow.max.x` is a signed 32-bit value in the EXR file format, so
`numBlocksX` can reach `(INT32_MAX + 7) / 8 = 268,435,456`. At that
point `numBlocksX * 64 = 17,179,869,184` overflows `int32`, and
`numBlocksX * numBlocksY` overflows even sooner. The wraparound
produces a small or negative pointer offset, causing `rowBlock[comp]`
and `currDcComp[comp]` to point into already-used or pre-buffer memory
rather than the intended component stride.
Fix: cast `numBlocksX` to `size_t` before multiplying so the
arithmetic is performed in pointer-sized unsigned arithmetic:
rowBlock[comp] = rowBlock[comp - 1] + (size_t) numBlocksX * 64;
currDcComp[comp] = currDcComp[comp - 1] + (size_t) numBlocksX * numBlocksY;
This is consistent with the allocation on the line above, which already
uses `(size_t) numComp * (size_t) numBlocksX * 64 * sizeof(uint16_t)`,
and with the packed-DC count check, which uses explicit `uint64_t` casts.
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
---
pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
index bcdebd985..e289b064d 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
@@ -265,7 +265,7 @@ LossyDctDecoder_execute (
}
for (int comp = 1; comp < numComp; ++comp)
- rowBlock[comp] = rowBlock[comp - 1] + numBlocksX * 64;
+ rowBlock[comp] = rowBlock[comp - 1] + (size_t) numBlocksX * 64;
//
// Pack DC components together by common plane, so we can get
@@ -275,7 +275,7 @@ LossyDctDecoder_execute (
currDcComp[0] = (uint16_t*) d->_packedDc;
for (int comp = 1; comp < numComp; ++comp)
- currDcComp[comp] = currDcComp[comp - 1] + numBlocksX * numBlocksY;
+ currDcComp[comp] = currDcComp[comp - 1] + (size_t) numBlocksX * numBlocksY;
for (int blocky = 0; blocky < numBlocksY; ++blocky)
{
--
2.53.0
From 5240e8159a07033477b94c2ad359bb7e3f20ed2d Mon Sep 17 00:00:00 2001
From: Cary Phillips <cary@ilm.com>
Date: Tue, 31 Mar 2026 07:49:09 -0700
Subject: [PATCH 6/6] =?UTF-8?q?Fix=20misaligned=20memory=20access=20in=20`?=
=?UTF-8?q?LossyDctDecoder=5Fexecute`=20HALF=E2=86=92FLOAT=20expansion=20(?=
=?UTF-8?q?#2324)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Fix misaligned memory access in `LossyDctDecoder_execute` HALF→FLOAT expansion
After DCT decoding, `LossyDctDecoder_execute()` expands FLOAT-type channels
from their intermediate HALF (16-bit) XDR representation back to FLOAT (32-bit)
XDR in place. The expansion was done by casting `_rows[y]` (a `uint8_t *`)
directly to `float *` and `uint16_t *`, then reading and writing through those
typed pointers.
Because row buffers are assigned by advancing a byte pointer with no alignment
padding (`outBufferEnd += chan->width * chan->bytes_per_element` in
`internal_dwa_compressor.h`), a FLOAT channel that follows a HALF channel of
odd width receives a `_rows[y]` pointer that is 2-byte aligned but not 4-byte
aligned. Dereferencing a `float *` cast from such a pointer is undefined
behavior under the C standard:
- On ARM, RISC-V, and MIPS (strict alignment) this crashes immediately.
- On x86 it is silently tolerated at the hardware level but remains UB:
auto-vectorizing compilers (SSE/AVX) may assume aligned access and generate
incorrect code.
- UBSan reports: `store to misaligned address ... for type 'float', which
requires 4 byte alignment` at `internal_dwa_decoder.h:749`.
Fix: replace the cast-and-dereference pattern with the `unaligned_load16` /
`memcpy` / `unaligned_store32` helpers already used throughout the rest of
OpenEXRCore (`internal_xdr.h`, `unpack.c`, `pack.c`, `internal_pxr24.c`).
These helpers use `memcpy` internally, which the C standard guarantees is safe
for unaligned addresses and which compilers compile to a single load/store
instruction on architectures that support it.
The byte-order handling is preserved correctly:
- `unaligned_load16` reads 2 bytes via `memcpy` and applies `one_to_native16`
(XDR → native), returning a native-endian HALF value.
- `half_to_float` converts native HALF → native float.
- `memcpy(&bits, &f, 4)` reinterprets the float's bit pattern as `uint32_t`
without numeric conversion (the correct type-pun idiom in C).
- `unaligned_store32` applies `one_from_native32` (native → XDR) and writes
4 bytes via `memcpy`, storing the result in XDR float format.
Made-with: Cursor
Signed-off-by: Cary Phillips <cary@ilm.com>
* add TODO comment
Signed-off-by: Cary Phillips <cary@ilm.com>
---------
Signed-off-by: Cary Phillips <cary@ilm.com>
---
.../OpenEXR/OpenEXRCore/internal_dwa_decoder.h | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
index e289b064d..046615ec5 100644
--- a/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
+++ b/pxr/imaging/hio/OpenEXR/OpenEXRCore/internal_dwa_decoder.h
@@ -651,13 +651,22 @@ LossyDctDecoder_execute (
/* process in place in reverse to avoid temporary buffer */
for (int y = 0; y < d->_height; ++y)
{
- float* floatXdrPtr = (float*) chanData[chan]->_rows[y];
- uint16_t* halfXdr = (uint16_t*) floatXdrPtr;
+ uint8_t* rowBytes = chanData[chan]->_rows[y];
for (int x = d->_width - 1; x >= 0; --x)
{
- floatXdrPtr[x] = one_from_native_float (
- half_to_float (one_to_native16 (halfXdr[x])));
+ // TODO: make an unaligned_store32f that takes the float and
+ // packages up a one_from_native_float and calls memcpy
+ // instead of the two memcpy. We should look at the metrics
+ // for dwa and see if there's a performance difference to do
+ // so at some point. See:
+ // https://github.com/AcademySoftwareFoundation/openexr/pull/2324
+
+ uint16_t h = unaligned_load16 (rowBytes + x * sizeof (uint16_t));
+ float f = half_to_float (h);
+ uint32_t bits;
+ memcpy (&bits, &f, sizeof (bits));
+ unaligned_store32 (rowBytes + x * sizeof (float), bits);
}
}
}
--
2.53.0

View file

@ -8,9 +8,7 @@
%bcond draco 1
%bcond embree 1
%bcond jemalloc 0
# Not yet packaged: https://github.com/AcademySoftwareFoundation/MaterialX
# https://bugzilla.redhat.com/show_bug.cgi?id=2262694
%bcond materialx 0
%bcond materialx 1
# Default "UNIX Makefiles" backend for CMake would also work fine; ninja is a
# bit faster. We conditionalize it just in case there are backend-specific
# issues in the future.
@ -151,6 +149,42 @@ Patch: 0005-Downstream-only-use-the-system-libdeflate.patch
# Downstream-only: use the system libavif library
Patch: 0006-Downstream-only-use-the-system-libavif.patch
# Backport fixes for CVE-2025-64181 etc. in OpenEXRCore
# https://github.com/PixarAnimationStudios/OpenUSD/pull/3903
# Rebased on v25.08
Patch: 0001-Backport-fixes-for-CVE-2025-64181-etc.-in-OpenEXRCor.patch
# sdf: Guard against invalid primChildren in crate files
# https://github.com/PixarAnimationStudios/OpenUSD/commit/b9530922b6a8ea72cd43661226b693fff8abbe4c
#
# Fixes:
#
# CVE-2025-14439 usd: OpenUSD File Parsing Use-After-Free Remote Code Execution
# Vulnerability [fedora-43]
# https://bugzilla.redhat.com/show_bug.cgi?id=2422276
#
# …which is:
#
# OpenUSD File Parsing Use-After-Free Remote Code Execution Vulnerability
# https://github.com/advisories/GHSA-grjp-54v3-c442
#
# Cherry-picked on v25.08.
Patch: 0001-sdf-Guard-against-invalid-primChildren-in-crate-file.patch
# Backport fix for CVE-2026-34544 in OpenEXRCore
# https://github.com/PixarAnimationStudios/OpenUSD/pull/4028
# Cherry-picked on v25.08.
Patch: 0001-Fix-B44-B44A-integer-overflow-use-uint64_t-for-row-o.patch
# Backport several OpenEXRCore security fixes
# https://github.com/PixarAnimationStudios/OpenUSD/pull/4030
# Fixes:
# - CVE-2026-34378 / GHSA-v76p-4qvv-vh4g / RHBZ#2455493
# - CVE-2026-34380 / GHSA-q3v8-hw4m-59w5 / RHBZ#2455534
# - CVE-2026-34588 / GHSA-588r-cr5c-w6hf / RHBZ#2455505
# - CVE-2026-34589 / GHSA-p8xc-w3q4-h64x / RHBZ#2455501
# - CVE-2026-34379 / GHSA-w88v-vqhq-5p24 / RHBZ#2455497
# Cherry-picked on v25.08.
Patch: usd-25.08-pr-4030.patch
# Base
BuildRequires: gcc-c++
@ -161,12 +195,20 @@ BuildRequires: ninja-build
BuildRequires: dos2unix
BuildRequires: help2man
# For applying 0001-sdf-Guard-against-invalid-primChildren-in-crate-file.patch,
# which includes binary diffs.
BuildRequires: git-core
BuildRequires: pkgconfig(blosc)
BuildRequires: pkgconfig(dri)
BuildRequires: hdf5-devel
BuildRequires: cmake(OpenSubdiv)
BuildRequires: pkgconfig(tbb)
# This seems to be an indirect dependency, probably through OpenSubdiv.
# Ideally, everything would take care of its own dependencies, and we wouldnt
# have to specify it directly, but we havent studied the problem closely
# enough to propose a fix.
BuildRequires: pkgconfig(OpenCL)
# Unbundled:
BuildRequires: cmake(double-conversion)
BuildRequires: pkgconfig(liblz4)
@ -199,6 +241,13 @@ BuildRequires: embree-devel
BuildRequires: pkgconfig(jemalloc)
%endif
%if %{with materialx}
BuildRequires: cmake(materialx)
BuildRequires: materialx-data
BuildRequires: pkgconfig(xt)
BuildRequires: python3-materialx
%endif
%if %{with ocio}
BuildRequires: cmake(OpenColorIO)
%endif
@ -234,12 +283,11 @@ BuildRequires: pkgconfig(ptex)
# CVE-2023-45664
# CVE-2023-45666
# CVE-2023-45667
BuildRequires: stb_image-devel >= 2.28^20231011gitbeebb24-12
BuildRequires: stb_image-static
BuildRequires: stb_image_write-devel >= 1.16
BuildRequires: stb_image_write-static
BuildRequires: stb_image_resize-devel >= 0.97
BuildRequires: stb_image_resize-static
# https://github.com/nothings/stb/issues/1860
# https://github.com/nothings/stb/issues/1861
BuildRequires: stb_image-static >= 2.30^20251025gitf1c79c0-2
BuildRequires: stb_image_write-static >= 1.16
BuildRequires: stb_image_resize-static >= 0.97
Requires: usd-libs%{?_isa} = %{version}-%{release}
Requires: python3-usd%{?_isa} = %{version}-%{release}
@ -250,7 +298,7 @@ Requires: python3-usd%{?_isa} = %{version}-%{release}
#
# Note that pxr/base/arch/assumptions.cpp explicitly tests the machine is not
# big-endian, and pxr/base/arch/defines.h explicitly enforces x86_64 or ARM64.
ExclusiveArch: aarch64 x86_64
ExclusiveArch: %{arm64} %{x86_64}
%description
Universal Scene Description (USD) is a time-sampled scene
@ -362,6 +410,11 @@ Requires: usd-libs%{?_isa} = %{version}-%{release}
# Unbundled, and exposed in the API:
Requires: cli11-devel cli11-static
Requires: robin-map-devel robin-map-static
# Needed by cmake config
Requires: cmake(OpenSubdiv)
%if %{with materialx}
Requires: cmake(materialx)
%endif
%description devel
This package contains the C++ header files and symbolic links to the shared
@ -398,7 +451,10 @@ Requires: usd-libs%{?_isa} = %{version}-%{release}
Python language bindings for the Universal Scene Description (USD) C++ API
%prep
%autosetup -p1 -n OpenUSD-%{version}
# The -S git is for applying
# 0001-sdf-Guard-against-invalid-primChildren-in-crate-file.patch, which
# includes binary diffs.
%autosetup -p1 -n OpenUSD-%{version} -S git
# Convert NOTICE.txt from CRNL line encoding
dos2unix NOTICE.txt
@ -567,7 +623,6 @@ extra_flags="${extra_flags-} -DTBB_SUPPRESS_DEPRECATED_MESSAGES=1"
-DPXR_BUILD_ALEMBIC_PLUGIN=%{expr:%{with alembic}?"ON":"OFF"} \
-DPXR_BUILD_DRACO_PLUGIN=%{expr:%{with draco}?"ON":"OFF"} \
-DPXR_BUILD_EMBREE_PLUGIN=%{expr:%{with embree}?"ON":"OFF"} \
-DPXR_BUILD_MATERIALX_PLUGIN=%{expr:%{with materialx}?"ON":"OFF"} \
-DPXR_BUILD_OPENCOLORIO_PLUGIN=%{expr:%{with ocio}?"ON":"OFF"} \
-DPXR_BUILD_OPENIMAGEIO_PLUGIN=%{expr:%{with oiio}?"ON":"OFF"} \
-DPXR_BUILD_PRMAN_PLUGIN=OFF \
@ -577,6 +632,7 @@ extra_flags="${extra_flags-} -DTBB_SUPPRESS_DEPRECATED_MESSAGES=1"
-DPXR_ENABLE_PTEX_SUPPORT=%{expr:%{with ptex}?"ON":"OFF"} \
-DPXR_ENABLE_OSL_SUPPORT=%{expr:%{with openshading}?"ON":"OFF"} \
-DPXR_ENABLE_MALLOCHOOK_SUPPORT=OFF \
-DPXR_ENABLE_MATERIALX_SUPPORT=%{expr:%{with materialx}?"ON":"OFF"} \
-DPXR_ENABLE_PYTHON_SUPPORT=ON \
\
-DPXR_INSTALL_LOCATION="%{_libdir}/usd/plugin" \
@ -642,6 +698,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.openusd.usdview.d
%{_bindir}/hdGenSchema
%{_bindir}/sdfdump
%{_bindir}/sdffilter
%if %{with materialx}
%{_bindir}/usdBakeMaterialX
%endif
%{_bindir}/usdGenSchema
%{_bindir}/usdInitSchema
%{_bindir}/usdcat
@ -670,6 +729,9 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.openusd.usdview.d
%{_mandir}/man1/hdGenSchema.1*
%{_mandir}/man1/sdfdump.1*
%{_mandir}/man1/sdffilter.1*
%if %{with materialx}
%{_mandir}/man1/usdBakeMaterialX.1*
%endif
%{_mandir}/man1/usdGenSchema.1*
%{_mandir}/man1/usdInitSchema.1*
%{_mandir}/man1/usdcat.1*