CVE-2020-13112: Out-of-bounds Read (CWE-125)
value: An issue was discovered in libexif before 0.6.22. Several buffer over-reads in EXIF MakerNote handling could lead to information disclosure and crashes. This is different from CVE-2020-0093.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 9.1
Published: 2020-05-21T16:15Z
Repository: https://github.com/libexif/libexif
Language: C
Files changed: libexif/canon/exif-mnote-data-canon.c, libexif/fuji/exif-mnote-data-fuji.c, libexif/olympus/exif-mnote-data-olympus.c, libexif/pentax/exif-mnote-data-pentax.c
Commit date: 2020-05-16 17:34:01 +0200
Commit message: Fix MakerNote tag size overflow issues at read time.

Check for a size overflow while reading tags, which ensures that the
size is always consistent for the given components and type of the
entry, making checking further down superfluous.

This provides an alternate fix for
https://sourceforge.net/p/libexif/bugs/125/ CVE-2016-6328 and for all
the MakerNote types. Likely, this makes both commits 41bd0423 and
89e5b1c1 redundant as it ensures that MakerNote entries are well-formed
when they're populated.

Some improvements on top by Marcus Meissner <marcus@jet.franken.de>

CVE-2020-13112

Diff: diff --git a/libexif/canon/exif-mnote-data-canon.c b/libexif/canon/exif-mnote-data-canon.c
index ccaeb6a2..4e993251 100644
--- a/libexif/canon/exif-mnote-data-canon.c
+++ b/libexif/canon/exif-mnote-data-canon.c
@@ -28,10 +28,12 @@
 
 #include <libexif/exif-byte-order.h>
 #include <libexif/exif-utils.h>
 #include <libexif/exif-data.h>
 
+#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
+
 static void
 exif_mnote_data_canon_clear (ExifMnoteDataCanon *n)
 {
 	ExifMnoteData *d = (ExifMnoteData *) n;
 	unsigned int i;
@@ -207,11 +209,11 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,
 		exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteCanon", "Short MakerNote");
 		return;
 	}
 	datao = 6 + n->offset;
-	if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
+	if (CHECKOVERFLOW(datao, buf_size, 2)) {
 		exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteCanon", "Short MakerNote");
 		return;
 	}
 
@@ -231,25 +233,36 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,
 
 	/* Parse the entries */
 	tcount = 0;
 	for (i = c, o = datao; i; --i, o += 12) {
 		size_t s;
-		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+
+		if (CHECKOVERFLOW(o,buf_size,12)) {
 			exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
 				"ExifMnoteCanon", "Short MakerNote");
 			break;
-	        }
+		}
 
 		n->entries[tcount].tag        = exif_get_short (buf + o, n->order);
 		n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
 		n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
 		n->entries[tcount].order      = n->order;
 
 		exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon",
 			"Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
 			 mnote_canon_tag_get_name (n->entries[tcount].tag));
 
+		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
+		 * we will check the buffer sizes closer later. */
+		if (	exif_format_get_size (n->entries[tcount].format) &&
+			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
+		) {
+			exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
+				  "ExifMnoteCanon", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
+			continue;
+		}
+
 		/*
 		 * Size? If bigger than 4 bytes, the actual data is not
 		 * in the entry but somewhere else (offset).
 		 */
 		s = exif_format_get_size (n->entries[tcount].format) * 
@@ -262,11 +275,12 @@ exif_mnote_data_canon_load (ExifMnoteData *ne,
 			continue;
 
 		} else {
 			size_t dataofs = o + 8;
 			if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6;
-			if ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) {
+
+			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
 				exif_log (ne->log, EXIF_LOG_CODE_DEBUG,
 					"ExifMnoteCanon",
 					"Tag data past end of buffer (%u > %u)",
 					(unsigned)(dataofs + s), buf_size);
 				continue;
diff --git a/libexif/fuji/exif-mnote-data-fuji.c b/libexif/fuji/exif-mnote-data-fuji.c
index 726a1d38..6671e4cd 100644
--- a/libexif/fuji/exif-mnote-data-fuji.c
+++ b/libexif/fuji/exif-mnote-data-fuji.c
@@ -26,10 +26,12 @@
 #include <libexif/exif-byte-order.h>
 #include <libexif/exif-utils.h>
 
 #include "exif-mnote-data-fuji.h"
 
+#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
+
 struct _MNoteFujiDataPrivate {
 	ExifByteOrder order;
 };
 
 static void
@@ -160,20 +162,20 @@ exif_mnote_data_fuji_load (ExifMnoteData *en,
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataFuji", "Short MakerNote");
 		return;
 	}
 	datao = 6 + n->offset;
-	if ((datao + 12 < datao) || (datao + 12 < 12) || (datao + 12 > buf_size)) {
+	if (CHECKOVERFLOW(datao, buf_size, 12)) {
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataFuji", "Short MakerNote");
 		return;
 	}
 
 	n->order = EXIF_BYTE_ORDER_INTEL;
+
 	datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
-	if ((datao + 2 < datao) || (datao + 2 < 2) ||
-	    (datao + 2 > buf_size)) {
+	if (CHECKOVERFLOW(datao, buf_size, 2)) {
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataFuji", "Short MakerNote");
 		return;
 	}
 
@@ -193,11 +195,12 @@ exif_mnote_data_fuji_load (ExifMnoteData *en,
 
 	/* Parse all c entries, storing ones that are successfully parsed */
 	tcount = 0;
 	for (i = c, o = datao; i; --i, o += 12) {
 		size_t s;
-		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+
+		if (CHECKOVERFLOW(o, buf_size, 12)) {
 			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 				  "ExifMnoteDataFuji", "Short MakerNote");
 			break;
 		}
 
@@ -208,10 +211,19 @@ exif_mnote_data_fuji_load (ExifMnoteData *en,
 
 		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
 			  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
 			  mnote_fuji_tag_get_name (n->entries[tcount].tag));
 
+		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
+		 * we will check the buffer sizes closer later. */
+		if (	exif_format_get_size (n->entries[tcount].format) &&
+			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
+		) {
+			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+					  "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
+			continue;
+		}
 		/*
 		 * Size? If bigger than 4 bytes, the actual data is not
 		 * in the entry but somewhere else (offset).
 		 */
 		s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
@@ -219,12 +231,12 @@ exif_mnote_data_fuji_load (ExifMnoteData *en,
 		if (s) {
 			size_t dataofs = o + 8;
 			if (s > 4)
 				/* The data in this case is merely a pointer */
 				dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
-			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
-				(dataofs + s >= buf_size)) {
+
+			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
 				exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 						  "ExifMnoteDataFuji", "Tag data past end of "
 					  "buffer (%u >= %u)", (unsigned)(dataofs + s), buf_size);
 				continue;
 			}
diff --git a/libexif/olympus/exif-mnote-data-olympus.c b/libexif/olympus/exif-mnote-data-olympus.c
index 5a02a941..bd83411e 100644
--- a/libexif/olympus/exif-mnote-data-olympus.c
+++ b/libexif/olympus/exif-mnote-data-olympus.c
@@ -33,10 +33,12 @@
  * which is duplicated in IFD 1, and fixing the offset could actually cause
  * problems with other software that expects the broken form.
  */
 /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */
 
+#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
+
 static enum OlympusVersion
 exif_mnote_data_olympus_identify_variant (const unsigned char *buf,
 		unsigned int buf_size);
 
 
@@ -243,11 +245,11 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataOlympus", "Short MakerNote");
 		return;
 	}
 	o2 = 6 + n->offset; /* Start of interesting data */
-	if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
+	if (CHECKOVERFLOW(o2,buf_size,10)) {
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataOlympus", "Short MakerNote");
 		return;
 	}
 
@@ -298,11 +300,11 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 
 	case olympusV2:
 		/* Olympus S760, S770 */
 		datao = o2;
 		o2 += 8;
-		if ((o2 + 4 < o2) || (o2 + 4 < 4) || (o2 + 4 > buf_size)) return;
+		if (CHECKOVERFLOW(o2,buf_size,4)) return;
 		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
 			"Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...",
 			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
 
 		if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
@@ -339,11 +341,11 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 		}
 		break;
 
 	case nikonV2:
 		o2 += 6;
-		if ((o2 + 12 < o2) || (o2 + 12 < 12) || (o2 + 12 > buf_size)) return;
+		if (CHECKOVERFLOW(o2,buf_size,12)) return;
 		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
 			"Parsing Nikon maker note v2 (0x%02x, %02x, %02x, "
 			"%02x, %02x, %02x, %02x, %02x)...",
 			buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
 			buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
@@ -397,11 +399,11 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 			"Unknown Olympus variant %i.", n->version);
 		return;
 	}
 
 	/* Sanity check the offset */
-	if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
+	if (CHECKOVERFLOW(o2,buf_size,2)) {
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteOlympus", "Short MakerNote");
 		return;
 	}
 
@@ -421,11 +423,11 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 
 	/* Parse all c entries, storing ones that are successfully parsed */
 	tcount = 0;
 	for (i = c, o = o2; i; --i, o += 12) {
 		size_t s;
-		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+		if (CHECKOVERFLOW(o, buf_size, 12)) {
 			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 				  "ExifMnoteOlympus", "Short MakerNote");
 			break;
 		}
 
@@ -442,10 +444,18 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 		    n->entries[tcount].tag,
 		    n->entries[tcount].format,
 		    n->entries[tcount].components,
 		    (int)exif_format_get_size(n->entries[tcount].format)); */
 
+	    /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
+	     * we will check the buffer sizes closer later. */
+	    if (exif_format_get_size (n->entries[tcount].format) &&
+		buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
+	    ) {
+		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
+		continue;
+	    }
 	    /*
 	     * Size? If bigger than 4 bytes, the actual data is not
 	     * in the entry but somewhere else (offset).
 	     */
 	    s = exif_format_get_size (n->entries[tcount].format) *
@@ -460,21 +470,20 @@ exif_mnote_data_olympus_load (ExifMnoteData *en,
 				/* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
 				 * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE
 				 * tag in its MakerNote. The offset is actually the absolute
 				 * position in the file instead of the position within the IFD.
 				 */
-			    if (dataofs + s > buf_size && n->version == sanyoV1) {
+			    if (dataofs > (buf_size - s) && n->version == sanyoV1) {
 					/* fix pointer */
 					dataofs -= datao + 6;
 					exif_log (en->log, EXIF_LOG_CODE_DEBUG,
 						  "ExifMnoteOlympus",
 						  "Inconsistent thumbnail tag offset; attempting to recover");
 			    }
 #endif
 			}
-			if ((dataofs + s < dataofs) || (dataofs + s < s) || 
-			    (dataofs + s > buf_size)) {
+			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
 				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
 					  "ExifMnoteOlympus",
 					  "Tag data past end of buffer (%u > %u)",
 					  (unsigned)(dataofs + s), buf_size);
 				continue;
diff --git a/libexif/pentax/exif-mnote-data-pentax.c b/libexif/pentax/exif-mnote-data-pentax.c
index c7305c70..5f75d8f3 100644
--- a/libexif/pentax/exif-mnote-data-pentax.c
+++ b/libexif/pentax/exif-mnote-data-pentax.c
@@ -26,10 +26,12 @@
 #include <stdio.h>
 
 #include <libexif/exif-byte-order.h>
 #include <libexif/exif-utils.h>
 
+#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
+
 static void
 exif_mnote_data_pentax_clear (ExifMnoteDataPentax *n)
 {
 	ExifMnoteData *d = (ExifMnoteData *) n;
 	unsigned int i;
@@ -222,11 +224,11 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataPentax", "Short MakerNote");
 		return;
 	}
 	datao = 6 + n->offset;
-	if ((datao + 8 < datao) || (datao + 8 < 8) || (datao + 8 > buf_size)) {
+	if (CHECKOVERFLOW(datao, buf_size, 8)) {
 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 			  "ExifMnoteDataPentax", "Short MakerNote");
 		return;
 	}
 
@@ -275,11 +277,12 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,
 
 	/* Parse all c entries, storing ones that are successfully parsed */
 	tcount = 0;
 	for (i = c, o = datao; i; --i, o += 12) {
 		size_t s;
-		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+
+		if (CHECKOVERFLOW(o,buf_size,12)) {
 			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
 				  "ExifMnoteDataPentax", "Short MakerNote");
 			break;
 		}
 
@@ -290,10 +293,19 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,
 
 		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnotePentax",
 			  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
 			  mnote_pentax_tag_get_name (n->entries[tcount].tag));
 
+		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
+		 * we will check the buffer sizes closer later. */
+		if (	exif_format_get_size (n->entries[tcount].format) &&
+			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
+		) {
+			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+				  "ExifMnoteDataPentax", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
+			break;
+		}
 		/*
 		 * Size? If bigger than 4 bytes, the actual data is not
 		 * in the entry but somewhere else (offset).
 		 */
 		s = exif_format_get_size (n->entries[tcount].format) *
@@ -302,12 +314,12 @@ exif_mnote_data_pentax_load (ExifMnoteData *en,
 		if (s) {
 			size_t dataofs = o + 8;
 			if (s > 4)
 				/* The data in this case is merely a pointer */
 			   	dataofs = exif_get_long (buf + dataofs, n->order) + 6;
-			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
-				(dataofs + s > buf_size)) {
+
+			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
 				exif_log (en->log, EXIF_LOG_CODE_DEBUG,
 						  "ExifMnoteDataPentax", "Tag data past end "
 					  "of buffer (%u > %u)", (unsigned)(dataofs + s), buf_size);
 				continue;
 			}

Vulnerable code: 	if ((datao + 2 < datao) || (datao + 2 < 2) || (datao + 2 > buf_size)) {
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
	        }
			if ((dataofs + s < s) || (dataofs + s < dataofs) || (dataofs + s > buf_size)) {
	if ((datao + 12 < datao) || (datao + 12 < 12) || (datao + 12 > buf_size)) {
	if ((datao + 2 < datao) || (datao + 2 < 2) ||
	    (datao + 2 > buf_size)) {
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
				(dataofs + s >= buf_size)) {
	if ((o2 + 10 < o2) || (o2 + 10 < 10) || (o2 + 10 > buf_size)) {
		if ((o2 + 4 < o2) || (o2 + 4 < 4) || (o2 + 4 > buf_size)) return;
		if ((o2 + 12 < o2) || (o2 + 12 < 12) || (o2 + 12 > buf_size)) return;
	if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
			    if (dataofs + s > buf_size && n->version == sanyoV1) {
			if ((dataofs + s < dataofs) || (dataofs + s < s) || 
			    (dataofs + s > buf_size)) {
	if ((datao + 8 < datao) || (datao + 8 < 8) || (datao + 8 > buf_size)) {
		if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
			if ((dataofs + s < dataofs) || (dataofs + s < s) ||
				(dataofs + s > buf_size)) {
Fixed code: #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))

	if (CHECKOVERFLOW(datao, buf_size, 2)) {

		if (CHECKOVERFLOW(o,buf_size,12)) {
		}
		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
		 * we will check the buffer sizes closer later. */
		if (	exif_format_get_size (n->entries[tcount].format) &&
			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
		) {
			exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifMnoteCanon", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
			continue;
		}


			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))

	if (CHECKOVERFLOW(datao, buf_size, 12)) {

	if (CHECKOVERFLOW(datao, buf_size, 2)) {

		if (CHECKOVERFLOW(o, buf_size, 12)) {
		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
		 * we will check the buffer sizes closer later. */
		if (	exif_format_get_size (n->entries[tcount].format) &&
			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
		) {
			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
					  "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
			continue;
		}

			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))

	if (CHECKOVERFLOW(o2,buf_size,10)) {
		if (CHECKOVERFLOW(o2,buf_size,4)) return;
		if (CHECKOVERFLOW(o2,buf_size,12)) return;
	if (CHECKOVERFLOW(o2,buf_size,2)) {
		if (CHECKOVERFLOW(o, buf_size, 12)) {
	    /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
	     * we will check the buffer sizes closer later. */
	    if (exif_format_get_size (n->entries[tcount].format) &&
		buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
	    ) {
		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
		continue;
	    }
			    if (dataofs > (buf_size - s) && n->version == sanyoV1) {
			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
#define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))

	if (CHECKOVERFLOW(datao, buf_size, 8)) {

		if (CHECKOVERFLOW(o,buf_size,12)) {
		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
		 * we will check the buffer sizes closer later. */
		if (	exif_format_get_size (n->entries[tcount].format) &&
			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
		) {
			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
				  "ExifMnoteDataPentax", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
			break;
		}

			if (CHECKOVERFLOW(dataofs, buf_size, s)) {