From 08cddd985b67720478d83d6635a4144381e2ae80 Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Fri, 26 Jun 2026 19:47:08 -0400 Subject: [PATCH] fix(ico): Better error checking for PNG-in-ICO files, tighten res limits An ICO file might store its contents in PNG format, but it's still constrained to the resolution limits of ICO. Anything bigger should be presumed to be bogus. Signed-off-by: Larry Gritz --- src/ico.imageio/icoinput.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/ico.imageio/icoinput.cpp b/src/ico.imageio/icoinput.cpp index 1565fda4e3..09e6583e31 100644 --- a/src/ico.imageio/icoinput.cpp +++ b/src/ico.imageio/icoinput.cpp @@ -57,6 +57,7 @@ class ICOInput final : public ImageInput { int m_color_type; ///< PNG color model type int m_interlace_type; ///< PNG interlace type Imath::Color3f m_bg; ///< PNG background color + bool m_err = false; /// Reset everything to initial state /// @@ -65,6 +66,7 @@ class ICOInput final : public ImageInput { m_subimage = -1; m_png = NULL; m_info = NULL; + m_err = false; memset(&m_ico, 0, sizeof(m_ico)); m_buf.clear(); ioproxy_clear(); @@ -81,6 +83,7 @@ class ICOInput final : public ImageInput { ICOInput* icoinput = (ICOInput*)png_get_io_ptr(png_ptr); OIIO_DASSERT(icoinput); if (!icoinput->ioread(data, length)) { + icoinput->m_err = true; png_chunk_error(png_ptr, icoinput->geterror(false).c_str()); } } @@ -231,11 +234,15 @@ ICOInput::seek_subimage(int subimage, int miplevel) png_set_sig_bytes(m_png, 8); // already read 8 bytes - if (!PNG_pvt::read_info(m_png, m_info, m_bpp, m_color_type, - m_interlace_type, m_bg, m_spec, true)) - return false; - if (!check_open(m_spec, { 0, 1 << 20, 0, 1 << 20, 0, 1, 0, 4 })) + bool ok = PNG_pvt::read_info(m_png, m_info, m_bpp, m_color_type, + m_interlace_type, m_bg, m_spec, true); + if (!ok || m_err + || !check_open(m_spec, { 0, 256, 0, 256, 0, 1, 0, 4 })) { + // Technically, PNGs can be bigger, but we think nobody will make + // ICO files (even those that are png underneath) this big, so + // assume anything over 2^16 res is bogus. return false; + } m_spec.attribute("oiio:BitsPerSample", m_bpp / m_spec.nchannels); @@ -312,7 +319,7 @@ ICOInput::readimg() //std::cerr << "[ico] PNG buffer size = " << m_buf.size () << "\n"; - if (s.length()) { + if (s.length() || m_err || has_error()) { errorfmt("{}", s); return false; }