- for (i = 0; i < c; i++) {
- o = 6 + 2 + n->offset + 12 * i;
- if (o + 8 > buf_size) return;
-
- n->count = i + 1;
- n->entries = exif_mem_realloc (ne->mem, n->entries,
- sizeof (MnoteCanonEntry) * (i+1));
- memset (&n->entries[i], 0, sizeof (MnoteCanonEntry));
- n->entries[i].tag = exif_get_short (buf + o, n->order);
- n->entries[i].format = exif_get_short (buf + o + 2, n->order);
- n->entries[i].components = exif_get_long (buf + o + 4, n->order);
- n->entries[i].order = n->order;
-
- /*
- * 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[i].format) *
- n->entries[i].components;
- if (!s) return;
- o += 8;
- if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
- if (o + s > buf_size) return;
-
- /* Sanity check */
- n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s);
- if (!n->entries[i].data) return;
- n->entries[i].size = s;
- memcpy (n->entries[i].data, buf + o, s);
+ tcount = 0;
+ for (i = c, o = datao; i; --i, o += 12) {
+ size_t s;
+
+ memset(&n->entries[tcount], 0, sizeof(MnoteCanonEntry));
+ 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) *
+ n->entries[tcount].components;
+ n->entries[tcount].size = s;
+ if (!s) {
+ exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteCanon",
+ "Invalid zero-length tag size");
+ continue;
+
+ } else {
+ size_t dataofs = o + 8;
+ if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6;
+
+ 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;
+ }
+
+ n->entries[tcount].data = exif_mem_alloc (ne->mem, s);
+ if (!n->entries[tcount].data) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s);
+ continue;
+ }
+ memcpy (n->entries[tcount].data, buf + dataofs, s);
+ }
+
+ /* Tag was successfully parsed */
+ ++tcount;