Skip to content

v1.23.3 - security release

Latest

Choose a tag to compare

@farindk farindk released this 01 Sep 21:38

v1.23.3 is a security and bugfix release. It is ABI- and API-compatible with v1.23.2 and is a drop-in replacement.

One of the fixed issues is rated critical, so all users are strongly advised to upgrade.

Security fixes

(CVE numbers will be added when assigned.)

  • CVE-2026-XXXXX (GHSA-x8r2-mggj-j6wr) Heap buffer overflow (write) in the uncompressed (unci) mixed-interleave decoder when the two chroma components declare different bit depths. Both the written bytes and the overflow length are controlled by the file. (critical)
  • CVE-2026-XXXXX (GHSA-8fmq-r4pf-7m57) Permanent decoder deadlock through a reference cycle between an image and its alpha auxiliary image. The alpha edge was not covered by the cycle guard and re-entered a held mutex. (high)
  • CVE-2026-XXXXX (GHSA-w7mc-p8jc-p853) Heap out-of-bounds read in the YCbCr 4:2:0 to 16-bit interleaved RGB conversion when the chroma planes have a lower bit depth than luma. Heap memory could end up in the decoded image. YCbCr conversions with mismatched luma and chroma bit depths are now rejected. (high)
  • CVE-2026-XXXXX (GHSA-4jqm-2x34-6f6r) Heap buffer overflow in the SVT-AV1 encoder plugin when encoding a high-bit-depth alpha channel, and a double free on its send-picture error path. (high)
  • CVE-2026-XXXXX (GHSA-hh47-fhqr-cj2r) Incomplete fix for GHSA-73p7-m7gg-w2jv: the tile range check of the unci decoder (without icef) could still overflow, allowing an out-of-bounds read. (medium)
  • CVE-2026-XXXXX (GHSA-4h82-g446-83fm) Heap out-of-bounds read when converting odd-height 4:2:0 frames of an uncompressed (uncv) image sequence to RGB. (medium)
  • CVE-2026-XXXXX (GHSA-9rj8-5mp5-26c9) Out-of-bounds read in the RGB to YCbCr identity-matrix color conversion when the R, G, and B planes have different bit depths. (medium)
  • CVE-2026-XXXXX (GHSA-gh5q-69gg-c964) A clap property combined with an oversized ispe reached an assert() in the Fraction arithmetic and aborted the process (incomplete fix for GHSA-jc8f-p23p-5hjg). An error is returned instead. (medium)
  • (GHSA-mw6f-29j3-76f4) Several smaller findings: heif_image_handle_get_depth_image_handle() and heif_image_handle_get_depth_image_representation_info() dereferenced a null pointer on files without a depth image; the TIFF input decoder of the example tools had an unbounded EXIF tag allocation and a division by zero on zero YCbCr subsampling; assert()s in the PNG input decoder are now error returns; integer overflow in the Go binding's ImageAccess.GetPlane(); heif-view now verifies the decoded frame size before display. (medium)
  • (GHSA-8857-r8x5-7499) Undefined behavior (negative shift) in the HDR bit-depth up-conversion for target bit depths above 16. Such conversions are now rejected. (low)

Thanks to @hrjeon2, @alextwordfence, @Nora-Qiu, @ikkyu3, @Namron2000, @followboy1999, @the-vibe-dev, @hillalee, and @sonicnew for reporting these issues.

Hardening

  • unci: fixed a pointer wrap on 32-bit builds in the tile decoders that walk the data with a raw pointer (bytealign and block component-interleave, block pixel-interleave). A huge row_align_size wrapped the pointer past the bounds check and read out of bounds (found by OSS-Fuzz)
  • unci: the per-tile decode path (heif_image_handle_decode_image_tile()) now runs the same uncC layout checks as the full-image path; a block-pixel layout with oversized component bit depths caused an undefined shift
  • unci: the sequence decode path rejects an oversized row_align_size like the still-image path
  • AVC SPS: variable-length fields are validated
  • Color conversion: fixed a negative shift when up-converting an alpha channel to more than twice its bit depth (e.g. 2-bit alpha with 12-bit color in an unci image), a signed overflow when compositing alpha on 16-bit images, and a missing chroma bit-depth check in the YCbCr 4:2:0 to 16-bit RGB conversion
  • Pixel plane allocation: the size computation is guarded against 64-bit overflow (reachable only with the image-size security limit disabled)
  • heif_region_item_add_region_polygon() checks its parameters (NULL pointer, negative point count)
  • Fixed a data race (broken double-checked locking) when pasting decoded grid tiles into the output image (#1888)
  • ID allocation: avoid an unsigned wrap when the maximum ID is reserved (fuzzer with -fsanitize=integer)

Bug fixes

  • Regression since v1.22.0: images with a clap crop, and small images whose coded frame is padded (hardware encoders), failed with "Security limit exceeded" even with limits disabled. The tightened decode size limit introduced with #1798 is now derived from the ispe size with a floor of 256x256 (#1856)
  • Regression since v1.21.0: YCbCr images with more than 14 bits per pixel could not be converted to RGB. The 14-bit limit now applies only to the YCgCo-Re integer path (#1881)
  • ftyp box parse errors are reported as such instead of "No 'ftyp' box", and a brands security limit of 0 (LIBHEIF_SECURITY_LIMITS=off) is treated as no limit (#1872)
  • When no tile of a grid image could be decoded, the tile decoding error is returned instead of an unspecific error, and the missing-decoder error now names the compression format and an example plugin (#1876)
  • AVC: fixed the SPS conformance window crop unit scaling. Encoded AVC images with dimensions that are not a multiple of 16 got an oversized ispe and a spurious clap property, and then failed to decode (#1866)
  • iloc: reading a sub-range of an extent stored in idat failed with "Not enough data present in 'iloc'", so multi-tile or icef-compressed uncompressed images stored in idat could not be decoded
  • Files with a mime item whose content encoding is unknown or whose decompressor is not compiled in are no longer rejected as a whole. The item's raw data stays accessible through heif_item_get_item_data(). The "identity" content encoding is treated as no encoding
  • heif_item_get_item_data() crashed on an item that was just added to a context (in-memory extents are now served directly)
  • heif_context_add_item(), heif_context_add_mime_item(), heif_context_add_precompressed_mime_item(), and heif_context_add_uri_item() aborted on NULL strings or data and on a negative size; they return a usage error now. heif_context_add_item() wrote a file with a 'pict' handler and a bogus pitm that no reader accepted
  • Encoders write the pixel aspect ratio into the bitstream where the codec supports it (Extended_SAR in the HEVC/AVC/VVC VUI, JFIF density fields), so the bitstream agrees with the pasp property (#1860)
  • x264: nclx color signalling was silently not written into the SPS VUI, producing a warning about disagreeing colr box and bitstream on decode
  • SVT-AV1 (>= 4.0.0): the QP derived from the quality setting is no longer rounded to an integer (quarter-QP steps). The value is written directly into the encoder configuration, avoiding a locale-dependent string round trip and an unintended switch from CRF to CQP rate control (#1867)
  • aom: wrong chroma plane height for 4:2:2 input
  • rav1e: the encoder was configured with the storage bit depth instead of the actual bit depth
  • OpenJPH: high-bit-depth source samples were read as 8-bit
  • uvg266: the high-bit-depth plane copy dropped the bytes-per-sample factor
  • OpenJPEG: lossless encoding was still rate-limited, producing truncated codestreams with visible errors
  • FFmpeg decoder: 12, 14, and 16-bit monochrome images (including alpha planes of such images) are decoded; high-bit-depth JPEG and JPEG 2000 are returned at the coded bit depth instead of as scaled 16-bit; an nclx profile is only attached for codecs that carry CICP signalling (AVC, HEVC, VVC, AV1), fixing wrong colors of JPEG 2000 images; big-endian hosts are supported
  • gdk-pixbuf: GError is set when stop_load() fails
  • Box_udes: fixed the dump output of the 'tags' field
  • CMake: HAVE_BROTLI and HAVE_LIBSHARPYUV are no longer propagated in the public interface; fixed the Brotli configuration

Behavior changes

  • heif_context_write() / heif_context_write_to_file() refuse a context that was read from a file (Unsupported_feature). Item and sample data were never copied from the input, so the written file was truncated. Writing a context that contains only metadata items (no image, no sequence) returns a usage error instead of writing an invalid ftyp box
  • YCbCr to RGB conversions where the chroma planes have a different bit depth than luma return heif_suberror_Unsupported_color_conversion
  • Alpha compositing (flattening) rejects images with more than 16 bits per sample; HDR up-conversion to more than 16 bits is rejected
  • The x265 encoder returns an error for images with more than 142,606,336 luma samples (the HEVC Level 7.2 maximum, e.g. 16384x8704) instead of crashing inside x265 (GHSA-2c3g-p585-8rpq)

Other

  • New heif_item_type_* and heif_entity_group_* fourcc constants, and documentation of the entity group types, in the API headers (#1864)
  • The uncompressed codec is no longer labeled experimental in heif-enc and the CMake options (#1869)
  • CI: Linux jobs moved to Ubuntu 24.04, GCC 16 added to the compiler matrix, clang-tidy performance checks enabled, all GitHub Actions pinned to commit SHAs, Coverity scan re-enabled