Commit 7ecce712 for libheif

commit 7ecce712b3f67231496ec5f82c4d618219ee20da
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Mon Aug 24 21:47:47 2026 +0200

    fix sign of NAL unit length in the openh264 decoder

    The four length bytes are uint8_t and promote to 'int' before shifting, so a
    leading byte >= 0x80 shifted left by 24 lands in the sign bit. The
    OR-expression is then a negative int that is implicitly converted to the
    uint32_t it gets assigned to, meaning the bounds check on the following line
    works on a value that arrived by accident.

    C++20 defines the shift itself, so only the 'integer' sanitizer catches this,
    not 'shift'. Compute in uint32_t instead.

diff --git a/libheif/plugins/decoder_openh264.cc b/libheif/plugins/decoder_openh264.cc
index d3063055..28793815 100644
--- a/libheif/plugins/decoder_openh264.cc
+++ b/libheif/plugins/decoder_openh264.cc
@@ -235,7 +235,12 @@ heif_error openh264_decode_next_image2(void* decoder_raw, heif_image** out_img,
         return kError_EOF;
       }

-      uint32_t size = ((indata[idx] << 24) | (indata[idx + 1] << 16) | (indata[idx + 2] << 8) | indata[idx + 3]);
+      // Compute in uint32_t. The bytes promote to 'int', so a leading byte >= 0x80
+      // shifted left by 24 lands in the sign bit and the result would be negative.
+      uint32_t size = (static_cast<uint32_t>(indata[idx]) << 24) |
+                      (static_cast<uint32_t>(indata[idx + 1]) << 16) |
+                      (static_cast<uint32_t>(indata[idx + 2]) << 8) |
+                      static_cast<uint32_t>(indata[idx + 3]);
       idx += 4;

       if (indata.size() < size || indata.size() - size < idx) {