From d9ab207ac075bc4822e31a09cef5283cacb41b6a Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Thu, 26 Mar 2026 17:08:25 -0700 Subject: [PATCH 1/2] fix: fix possible fmt exceptions where we might have passed null string I've heard occasional reports of uncaught exceptions in print statements. I haven't caught it in the act yet, but one set of reports involved the following output: OpenImageIO/detail/fmt/format-inl.h:40: assertion failed: string pointer is null So I'm proactively trying to find places that might be passing a null as a string. I'm just guessing here, but these are plausible candidates. Signed-off-by: Larry Gritz --- src/libutil/strutil_test.cpp | 8 ++++++++ src/libutil/ustring_test.cpp | 6 ++++++ src/raw.imageio/rawinput.cpp | 25 ++++++++++++++++--------- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/libutil/strutil_test.cpp b/src/libutil/strutil_test.cpp index f41538a530..98e3dfbd17 100644 --- a/src/libutil/strutil_test.cpp +++ b/src/libutil/strutil_test.cpp @@ -1328,6 +1328,14 @@ test_string_view() Strutil::print("addr cstr={:p}, s={:p}, ustring={:p}, sr={:p}, c_str(sr)={:p}\n", (void*)cstr, (void*)s.c_str(), (void*)ustring(cstr).c_str(), (void*)sr.data(), (void*)OIIO::c_str(sr)); + + // Test some edge cases for fmt formatting + string_view empty(""), uninit; + Strutil::print("Test print empty string_view: '{}'\n", empty); + Strutil::print("Test print default initialized string_view: '{}'\n", uninit); + OIIO_CHECK_EQUAL(empty, uninit); + OIIO_CHECK_EQUAL(Strutil::format("{}", empty), + Strutil::format("{}", uninit)); } diff --git a/src/libutil/ustring_test.cpp b/src/libutil/ustring_test.cpp index f50d1e2e07..464419d1f3 100644 --- a/src/libutil/ustring_test.cpp +++ b/src/libutil/ustring_test.cpp @@ -167,6 +167,12 @@ test_ustring() OIIO_CHECK_EQUAL(whichtype, ustring("foo")); OIIO_CHECK_ASSERT((std::is_same::value)); OIIO_CHECK_ASSERT(!(std::is_same::value)); + + // Test some edge cases for fmt formatting + Strutil::print("Test print empty ustring: '{}'\n", empty); + Strutil::print("Test print default initialized ustring: '{}'\n", uninit); + OIIO_CHECK_EQUAL(Strutil::format("{}", empty), + Strutil::format("{}", uninit)); } diff --git a/src/raw.imageio/rawinput.cpp b/src/raw.imageio/rawinput.cpp index 8fa7c6bc71..aba54ffd28 100644 --- a/src/raw.imageio/rawinput.cpp +++ b/src/raw.imageio/rawinput.cpp @@ -425,16 +425,18 @@ RawInput::open_raw(bool unpack, bool process, const std::string& name, int ret = m_processor->open_file(name.c_str()); #endif if (ret != LIBRAW_SUCCESS) { + const char* err = libraw_strerror(ret); errorfmt("Could not open file \"{}\", {}", m_filename, - libraw_strerror(ret)); + err ? err : "unknown error"); return false; } OIIO_ASSERT(!m_unpacked); if (unpack) { if ((ret = m_processor->unpack()) != LIBRAW_SUCCESS) { + const char* err = libraw_strerror(ret); errorfmt("Could not unpack \"{}\", {}", m_filename, - libraw_strerror(ret)); + err ? err : "unknown error"); return false; } m_unpacked = true; @@ -912,13 +914,15 @@ RawInput::open_raw(bool unpack, bool process, const std::string& name, // Get unadjusted max value (need to force a read first) ret = m_processor->raw2image_ex(/*subtract_black=*/true); if (ret != LIBRAW_SUCCESS) { - errorfmt("HighlightMode adjustment detection read failed"); - errorfmt("{}", libraw_strerror(ret)); + const char* err = libraw_strerror(ret); + errorfmt("HighlightMode adjustment detection read failed ({})", + err ? err : "unknown error"); return false; } if (m_processor->adjust_maximum() != LIBRAW_SUCCESS) { - errorfmt("HighlightMode minimum adjustment failed"); - errorfmt("{}", libraw_strerror(ret)); + const char* err = libraw_strerror(ret); + errorfmt("HighlightMode minimum adjustment failed ({})", + err ? err : "unknown error"); return false; } float unadjusted = m_processor->imgdata.color.maximum; @@ -929,8 +933,9 @@ RawInput::open_raw(bool unpack, bool process, const std::string& name, // Get new max value if (m_processor->adjust_maximum() != LIBRAW_SUCCESS) { - errorfmt("HighlightMode maximum adjustment failed"); - errorfmt("{}", libraw_strerror(ret)); + const char* err = libraw_strerror(ret); + errorfmt("HighlightMode maximum adjustment failed ({})", + err ? err : "unknown error"); return false; } float adjusted = m_processor->imgdata.color.maximum; @@ -1566,7 +1571,9 @@ RawInput::do_process() if (!m_image) { int ret = m_processor->dcraw_process(); if (ret != LIBRAW_SUCCESS) { - errorfmt("Processing image failed, {}", libraw_strerror(ret)); + const char* err = libraw_strerror(ret); + errorfmt("Processing image failed, {}", + err ? err : "unknown error"); return false; } From 6a02c767683e2ee2b67faf8844264dd22b875db9 Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Sat, 28 Mar 2026 15:04:17 -0700 Subject: [PATCH 2/2] Fix error with return code Signed-off-by: Larry Gritz --- src/raw.imageio/rawinput.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/raw.imageio/rawinput.cpp b/src/raw.imageio/rawinput.cpp index aba54ffd28..69b7b10e4d 100644 --- a/src/raw.imageio/rawinput.cpp +++ b/src/raw.imageio/rawinput.cpp @@ -919,7 +919,8 @@ RawInput::open_raw(bool unpack, bool process, const std::string& name, err ? err : "unknown error"); return false; } - if (m_processor->adjust_maximum() != LIBRAW_SUCCESS) { + ret = m_processor->adjust_maximum(); + if (ret != LIBRAW_SUCCESS) { const char* err = libraw_strerror(ret); errorfmt("HighlightMode minimum adjustment failed ({})", err ? err : "unknown error"); @@ -932,7 +933,8 @@ RawInput::open_raw(bool unpack, bool process, const std::string& name, = (old_max_thr == 0.0f) ? 1.0 : old_max_thr; // Get new max value - if (m_processor->adjust_maximum() != LIBRAW_SUCCESS) { + ret = m_processor->adjust_maximum(); + if (ret != LIBRAW_SUCCESS) { const char* err = libraw_strerror(ret); errorfmt("HighlightMode maximum adjustment failed ({})", err ? err : "unknown error");