Commit 2d0dfa0c for libheif
commit 2d0dfa0cbb8a37ad9e13c60c70e2800552a4d487
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Fri Dec 26 12:51:53 2025 +0100
function for safe 4x uint8_t to uint32_t conversion
diff --git a/examples/common.cc b/examples/common.cc
index 1f3a8d62..04408a1f 100644
--- a/examples/common.cc
+++ b/examples/common.cc
@@ -32,6 +32,8 @@
#include <vector>
#include <algorithm>
+#include "common_utils.h"
+
namespace heif_examples {
void show_version()
{
@@ -121,7 +123,7 @@ namespace heif_examples {
std::array<uint8_t, 4> length{};
istr.read((char*) length.data(), length.size());
- uint32_t box_size = (length[0] << 24) + (length[1] << 16) + (length[2] << 8) + (length[3]);
+ uint32_t box_size = four_bytes_to_uint32(length[0], length[1], length[2], length[3]);
if ((box_size < 16) || (box_size > 512)) {
fprintf(stderr, "Input file does not appear to start with a valid box length.");
if ((box_size & 0xFFFFFFF0) == 0xFFD8FFE0) {
diff --git a/examples/heif_dec.cc b/examples/heif_dec.cc
index a621d9ff..14cbaa3c 100644
--- a/examples/heif_dec.cc
+++ b/examples/heif_dec.cc
@@ -68,6 +68,7 @@
#include "../heifio/encoder_y4m.h"
#include "common.h"
+#include "common_utils.h"
#if defined(_MSC_VER)
#include "getopt.h"
@@ -458,7 +459,7 @@ int decode_single_image(heif_image_handle* handle,
return 1;
}
- offset = (exif[0] << 24) | (exif[1] << 16) | (exif[2] << 8) | exif[3];
+ offset = four_bytes_to_uint32(exif[0], exif[1], exif[2], exif[3]);
offset += 4;
if (offset >= exifSize) {
diff --git a/heifio/encoder_jpeg.cc b/heifio/encoder_jpeg.cc
index 040fe37d..c38d4cb4 100644
--- a/heifio/encoder_jpeg.cc
+++ b/heifio/encoder_jpeg.cc
@@ -35,6 +35,8 @@
#include <jpeglib.h>
+#include "common_utils.h"
+
#define JPEG_XMP_MARKER (JPEG_APP0+1) /* JPEG marker code for XMP */
#define JPEG_XMP_MARKER_ID "http://ns.adobe.com/xap/1.0/"
@@ -182,7 +184,7 @@ bool JpegEncoder::Encode(const struct heif_image_handle* handle,
if (exifsize > 4) {
static const uint8_t kExifMarker = JPEG_APP0 + 1;
- uint32_t skip = (exifdata[0] << 24) | (exifdata[1] << 16) | (exifdata[2] << 8) | exifdata[3];
+ uint32_t skip = four_bytes_to_uint32(exifdata[0], exifdata[1], exifdata[2], exifdata[3]);
if (skip > (exifsize - 4)) {
fprintf(stderr, "Invalid EXIF data (offset too large)\n");
free(exifdata);
diff --git a/heifio/encoder_png.cc b/heifio/encoder_png.cc
index dc2d1adb..9f82466e 100644
--- a/heifio/encoder_png.cc
+++ b/heifio/encoder_png.cc
@@ -30,6 +30,8 @@
#include <vector>
#include "encoder_png.h"
+
+#include "common_utils.h"
#include "exif.h"
PngEncoder::PngEncoder() = default;
@@ -44,10 +46,10 @@ bool fix_icc_profile(uint8_t* profile_data, uint32_t& profile_size)
// --- check that profile size specified in header matches the real size
- uint32_t size_in_header = ((profile_data[0] << 24) |
- (profile_data[1] << 16) |
- (profile_data[2] << 8) |
- (profile_data[3] << 0));
+ uint32_t size_in_header = four_bytes_to_uint32(profile_data[0],
+ profile_data[1],
+ profile_data[2],
+ profile_data[3]);
if (size_in_header != profile_size) {
@@ -157,7 +159,7 @@ bool PngEncoder::Encode(const heif_image_handle* handle,
uint8_t* exifdata = GetExifMetaData(handle, &exifsize);
if (exifdata) {
if (exifsize > 4) {
- uint32_t skip = (exifdata[0] << 24) | (exifdata[1] << 16) | (exifdata[2] << 8) | exifdata[3];
+ uint32_t skip = four_bytes_to_uint32(exifdata[0], exifdata[1], exifdata[2], exifdata[3]);
if (skip < (exifsize - 4)) {
skip += 4;
uint8_t* ptr = exifdata + skip;
diff --git a/heifio/exif.cc b/heifio/exif.cc
index 33d55f2c..e0ffd889 100644
--- a/heifio/exif.cc
+++ b/heifio/exif.cc
@@ -21,6 +21,8 @@
#include <cassert>
#include "exif.h"
+#include "common_utils.h"
+
#define EXIF_TYPE_SHORT 3
#define EXIF_TYPE_LONG 4
#define DEFAULT_EXIF_ORIENTATION 1
@@ -41,10 +43,10 @@ static uint32_t read32(const uint8_t* data, uint32_t size, uint32_t pos, bool li
const uint8_t* p = data + pos;
if (littleEndian) {
- return (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
+ return four_bytes_to_uint32(p[3], p[2], p[1], p[0]);
}
else {
- return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+ return four_bytes_to_uint32(p[0], p[1], p[2], p[3]);
}
}
@@ -56,10 +58,10 @@ static uint16_t read16(const uint8_t* data, uint32_t size, uint32_t pos, bool li
const uint8_t* p = data + pos;
if (littleEndian) {
- return static_cast<uint16_t>((p[1] << 8) | p[0]);
+ return two_bytes_to_uint16(p[1], p[0]);
}
else {
- return static_cast<uint16_t>((p[0] << 8) | p[1]);
+ return two_bytes_to_uint16(p[0], p[1]);
}
}
diff --git a/libheif/bitstream.cc b/libheif/bitstream.cc
index 79c60c6d..4ac2805d 100644
--- a/libheif/bitstream.cc
+++ b/libheif/bitstream.cc
@@ -24,6 +24,8 @@
#include <cstring>
#include <cassert>
+#include "common_utils.h"
+
#if !defined(HAVE_BIT)
#include <type_traits>
#else
@@ -268,10 +270,7 @@ uint32_t BitstreamRange::read32()
return 0;
}
- return (uint32_t) ((buf[0] << 24) |
- (buf[1] << 16) |
- (buf[2] << 8) |
- (buf[3]));
+ return four_bytes_to_uint32(buf[0], buf[1], buf[2], buf[3]);
}
diff --git a/libheif/common_utils.h b/libheif/common_utils.h
index 00e2ef91..88ac12f3 100644
--- a/libheif/common_utils.h
+++ b/libheif/common_utils.h
@@ -35,12 +35,23 @@
#endif
-constexpr inline uint32_t fourcc(const char* id)
+constexpr uint32_t four_bytes_to_uint32(uint8_t msb, uint8_t b, uint8_t c, uint8_t lsb)
{
- return (((((uint32_t) id[0])&0xFF) << 24) |
- ((((uint32_t) id[1])&0xFF) << 16) |
- ((((uint32_t) id[2])&0xFF) << 8) |
- ((((uint32_t) id[3])&0xFF) << 0));
+ return (static_cast<uint32_t>(msb << 24) |
+ static_cast<uint32_t>(b << 16) |
+ static_cast<uint32_t>(c << 8) |
+ static_cast<uint32_t>(lsb));
+}
+
+constexpr uint16_t two_bytes_to_uint16(uint8_t msb, uint8_t lsb)
+{
+ return (static_cast<uint16_t>(msb << 8) |
+ static_cast<uint16_t>(lsb));
+}
+
+constexpr uint32_t fourcc(const char* id)
+{
+ return four_bytes_to_uint32(id[0], id[1], id[2], id[3]);
}
std::string fourcc_to_string(uint32_t code);
diff --git a/libheif/context.cc b/libheif/context.cc
index 6a960453..aa263887 100644
--- a/libheif/context.cc
+++ b/libheif/context.cc
@@ -1033,7 +1033,7 @@ Error HeifContext::interpret_heif_file_images()
if (!regionDataResult) {
return regionDataResult.error();
}
- region_item->parse(*regionDataResult);
+ region_item->parse(*regionDataResult, get_security_limits());
if (iref_box) {
std::vector<Box_iref::Reference> references = iref_box->get_references_from(id);
diff --git a/libheif/image-items/grid.cc b/libheif/image-items/grid.cc
index 3bda1d52..a4251557 100644
--- a/libheif/image-items/grid.cc
+++ b/libheif/image-items/grid.cc
@@ -60,22 +60,12 @@ Error ImageGrid::parse(const std::vector<uint8_t>& data)
"Grid image data incomplete"};
}
- m_output_width = ((static_cast<uint32_t>(data[4]) << 24) |
- (static_cast<uint32_t>(data[5]) << 16) |
- (static_cast<uint32_t>(data[6]) << 8) |
- (static_cast<uint32_t>(data[7])));
-
- m_output_height = ((static_cast<uint32_t>(data[8]) << 24) |
- (static_cast<uint32_t>(data[9]) << 16) |
- (static_cast<uint32_t>(data[10]) << 8) |
- (static_cast<uint32_t>(data[11])));
+ m_output_width = four_bytes_to_uint32(data[4], data[5], data[6], data[7]);
+ m_output_height = four_bytes_to_uint32(data[8], data[9], data[10], data[11]);
}
else {
- m_output_width = ((static_cast<uint32_t>(data[4]) << 8) |
- (static_cast<uint32_t>(data[5])));
-
- m_output_height = ((static_cast<uint32_t>(data[6]) << 8) |
- (static_cast<uint32_t>(data[7])));
+ m_output_width = two_bytes_to_uint16(data[4], data[5]);
+ m_output_height = two_bytes_to_uint16(data[6], data[7]);
}
return Error::Ok;
diff --git a/libheif/plugins/decoder_ffmpeg.cc b/libheif/plugins/decoder_ffmpeg.cc
index 532d3c02..22e1bb33 100644
--- a/libheif/plugins/decoder_ffmpeg.cc
+++ b/libheif/plugins/decoder_ffmpeg.cc
@@ -237,10 +237,10 @@ static heif_error ffmpeg_push_data2(void *decoder_raw, const void *data, size_t
};
}
- uint32_t nal_size = ((static_cast<uint32_t>(cdata[ptr + 0]) << 24) |
- (static_cast<uint32_t>(cdata[ptr + 1]) << 16) |
- (static_cast<uint32_t>(cdata[ptr + 2]) << 8) |
- (static_cast<uint32_t>(cdata[ptr + 3])));
+ uint32_t nal_size = four_bytes_to_uint32(cdata[ptr + 0],
+ cdata[ptr + 1],
+ cdata[ptr + 2],
+ cdata[ptr + 3]);
ptr += 4;
if (nal_size > size - ptr) {
diff --git a/libheif/plugins/decoder_vvdec.cc b/libheif/plugins/decoder_vvdec.cc
index 301ff225..09515720 100644
--- a/libheif/plugins/decoder_vvdec.cc
+++ b/libheif/plugins/decoder_vvdec.cc
@@ -180,10 +180,7 @@ heif_error vvdec_push_data2(void* decoder_raw, const void* frame_data, size_t fr
const auto* data = (const uint8_t*) frame_data;
for (;;) {
- uint32_t size = ((((uint32_t) data[0]) << 24) |
- (((uint32_t) data[1]) << 16) |
- (((uint32_t) data[2]) << 8) |
- (data[3]));
+ uint32_t size = four_bytes_to_uint32(data[0], data[1], data[2], data[3]);
data += 4;