fix off-by-one in avifGetExifTiffHeaderOffset scan bound (#3400)
diff --git a/src/exif.c b/src/exif.c
index dc89060..42c3de8 100644
--- a/src/exif.c
+++ b/src/exif.c
@@ -11,7 +11,7 @@
const uint8_t tiffHeaderBE[4] = { 'M', 'M', 0, 42 };
const uint8_t tiffHeaderLE[4] = { 'I', 'I', 42, 0 };
exifSize = AVIF_MIN(exifSize, UINT32_MAX);
- for (*offset = 0; *offset + 4 < exifSize; ++*offset) {
+ for (*offset = 0; *offset + 4 <= exifSize; ++*offset) {
if (!memcmp(&exif[*offset], tiffHeaderBE, 4) || !memcmp(&exif[*offset], tiffHeaderLE, 4)) {
return AVIF_RESULT_OK;
}
diff --git a/tests/gtest/avifmetadatatest.cc b/tests/gtest/avifmetadatatest.cc
index 7fc531b..3808e12 100644
--- a/tests/gtest/avifmetadatatest.cc
+++ b/tests/gtest/avifmetadatatest.cc
@@ -409,6 +409,23 @@
AVIF_RESULT_OK);
}
+// The TIFF header may be located in the last four bytes of the payload.
+// avifGetExifTiffHeaderOffset() must still find it there.
+TEST(MetadataTest, ExifTiffHeaderOffsetAtEnd) {
+ const uint8_t kLittleEndian[] = {0x00, 0x00, 'I', 'I', 42, 0};
+ size_t offset;
+ ASSERT_EQ(avifGetExifTiffHeaderOffset(kLittleEndian, sizeof(kLittleEndian),
+ &offset),
+ AVIF_RESULT_OK);
+ EXPECT_EQ(offset, 2u);
+
+ const uint8_t kBigEndian[] = {0x00, 'M', 'M', 0, 42};
+ ASSERT_EQ(
+ avifGetExifTiffHeaderOffset(kBigEndian, sizeof(kBigEndian), &offset),
+ AVIF_RESULT_OK);
+ EXPECT_EQ(offset, 1u);
+}
+
//------------------------------------------------------------------------------
TEST(MetadataTest, ExtendedXMP) {