read past the end of a buffer and therefore a segfault.
Allow MakerNote parsing to continue even if one tag parses
incorrectly.
Log an error whenever memory allocation fails in MakerNote parsing.
+2009-09-24 Dan Fandrich <dan@coneharvesters.com>
+
+ * Fixed some problems in MakerNote parsing that could cause a
+ read past the end of a buffer and therefore a segfault.
+ * Allow MakerNote parsing to continue even if one tag parses
+ incorrectly.
+ * Log an error whenever memory allocation fails in MakerNote parsing.
+
2009-09-23 Dan Fandrich <dan@coneharvesters.com>
* Removed bogus "APEX" value from shutter speed display (thanks to
libexif-0.6.x:
- * Updated translations: nl, pl, sk, vi
* New translation: da
+ * Updated translations: cs, de, en_CA, nl, pl, sk, sv, vi
* Added some example programs
* libexif is now thread safe when the underlying C library is thread safe
and when each object allocated by libexif isn't used by more than one
removed from a file
* Changed exif_tag_get_support_level_in_ifd() to return a value when possible
when the data type for the given tag is unknown
+ * Added support for writing Pentax and Casio type2 MakerNotes
+ * Improved display of Pentax and Casio type2 MakerNotes
+ * Completely fixed bug #1617997 to display APEX values correctly
+ * Stopped some crashes due to read-beyond-buffer accesses in MakerNotes
+ * Don't abort MakerNote parsing after the first invalid tag
libexif-0.6.17 (2008-11-06):
* Updated translations: cs, de, pl, sk, vi
* This file contains changes visible to users.
* Small bug fixes (typos, memory leaks, ...) and feature
- enhancements (new tag types, ...) are not mentionened
+ enhancements (new tag types, ...) are not mentioned
explicitly.
* Apart from that, I would like to ask committers to update this
*/
*buf_size = 2 + n->count * 12 + 4;
*buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size);
+ return;
+ }
/* Save the number of entries */
exif_set_short (*buf, n->order, (ExifShort) n->count);
if (s & 1) ts += 1;
t = exif_mem_realloc (ne->mem, *buf,
sizeof (char) * ts);
- if (!t) return;
+ if (!t) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts);
+ return;
+ }
*buf = t;
*buf_size = ts;
doff = *buf_size - s;
{
ExifMnoteDataCanon *n = (ExifMnoteDataCanon *) ne;
ExifShort c;
- size_t i, o, s;
- MnoteCanonEntry *t;
+ size_t i, tcount, o, datao = 6 + n->offset;
+
+ if (!n || !buf || !buf_size || (datao + 2 < datao) ||
+ (datao + 2 < 2) || (datao + 2 > buf_size)) {
+ exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteCanon", "Short MakerNote");
+ return;
+ }
- if (!n || !buf || !buf_size || (buf_size < 6 + n->offset + 2)) return;
+ /* Read the number of tags */
+ c = exif_get_short (buf + datao, n->order);
+ datao += 2;
- /* Read the number of entries and remove old ones. */
- c = exif_get_short (buf + 6 + n->offset, n->order);
+ /* Remove any old entries */
exif_mnote_data_canon_clear (n);
+ /* Reserve enough space for all the possible MakerNote tags */
+ n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c);
+ if (!n->entries) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c);
+ return;
+ }
+
/* Parse the entries */
- for (i = 0; i < c; i++) {
- o = 6 + 2 + n->offset + 12 * i;
- if (o + 8 > buf_size) {
+ 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)) {
exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifMnoteCanon", "Short MakerNote");
- return;
+ break;
}
- t = exif_mem_realloc (ne->mem, n->entries,
- sizeof (MnoteCanonEntry) * (i + 1));
- if (!t) return; /* out of memory */
- n->count = i + 1;
- n->entries = t;
- 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;
+ 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[i].tag,
- mnote_canon_tag_get_name (n->entries[i].tag));
+ "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
+ mnote_canon_tag_get_name (n->entries[tcount].tag));
/*
* 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;
+ 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");
- return;
- }
- o += 8;
- if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
- if ((o + s < s) || (o + s < o) || (o + s > buf_size)) {
- exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifMnoteCanon",
- "Tag data past end of buffer (%u > %u)",
- o + s, buf_size);
- return;
+ 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)) {
+ exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteCanon",
+ "Tag data past end of buffer (%u > %u)",
+ 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);
}
- /* Sanity check */
- n->entries[i].data = exif_mem_alloc (ne->mem, sizeof (char) * s);
- if (!n->entries[i].data) return; /* out of memory */
- n->entries[i].size = s;
- memcpy (n->entries[i].data, buf + o, s);
+ /* Tag was successfully parsed */
+ ++tcount;
}
+ /* Store the count of successfully parsed tags */
+ n->count = tcount;
}
static unsigned int
if (!mem) return NULL;
d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon));
- if (!d) return NULL;
+ if (!d)
+ return NULL;
exif_mnote_data_construct (d, mem);
ExifMemFreeFunc free_func;
};
+/*! Default memory allocation function. */
static void *
exif_mem_alloc_func (ExifLong ds)
{
return calloc ((size_t) ds, 1);
}
+/*! Default memory reallocation function. */
static void *
exif_mem_realloc_func (void *d, ExifLong ds)
{
return realloc (d, (size_t) ds);
}
+/*! Default memory free function. */
static void
exif_mem_free_func (void *d)
{
{
ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
ExifLong c;
- size_t i, o, s, datao = 6 + n->offset;
- MnoteFujiEntry *t;
+ size_t i, tcount, o, datao = 6 + n->offset;
if (!n || !buf || !buf_size || (datao + 12 < datao) ||
- (datao + 12 < 12) || (datao + 12 > buf_size))
+ (datao + 12 < 12) || (datao + 12 > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataFuji", "Short MakerNote");
return;
+ }
- /* Read the number of entries and remove old ones. */
n->order = EXIF_BYTE_ORDER_INTEL;
datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
- if ((datao + 2 < datao) || (datao + 2 < 2))
+ if ((datao + 2 < datao) || (datao + 2 < 2) ||
+ (datao + 2 > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataFuji", "Short MakerNote");
return;
+ }
+
+ /* Read the number of tags */
c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
datao += 2;
+
+ /* Remove any old entries */
exif_mnote_data_fuji_clear (n);
- /* Parse the entries */
- for (i = 0; i < c; i++) {
- o = datao + 12 * i;
- if (datao + 12 > buf_size) {
+ /* Reserve enough space for all the possible MakerNote tags */
+ n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
+ if (!n->entries) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
+ return;
+ }
+
+ /* 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)) {
exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifMnoteDataFuji", "Short MakerNote");
- return;
+ break;
}
- t = exif_mem_realloc (en->mem, n->entries,
- sizeof (MnoteFujiEntry) * (i + 1));
- if (!t) return;
- n->count = i + 1;
- n->entries = t;
- memset (&n->entries[i], 0, sizeof (MnoteFujiEntry));
- 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;
+ 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 (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));
/*
* 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 + n->offset;
- if ((o + s < o) || (o + s < s) || (o + s > buf_size)) {
- exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifMnoteDataFuji", "Tag data past end of "
- "buffer (%u > %u)", o + s, buf_size);
- return;
+ s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
+ n->entries[tcount].size = s;
+ 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)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataFuji", "Tag data past end of "
+ "buffer (%u >= %u)", dataofs + s, buf_size);
+ continue;
+ }
+
+ n->entries[tcount].data = exif_mem_alloc (en->mem, s);
+ if (!n->entries[tcount].data) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
+ continue;
+ }
+ memcpy (n->entries[tcount].data, buf + dataofs, s);
}
- /* Sanity check */
- n->entries[i].data = exif_mem_alloc (en->mem, s);
- if (!n->entries[i].data) return;
- n->entries[i].size = s;
- memcpy (n->entries[i].data, buf + o, s);
+ /* Tag was successfully parsed */
+ ++tcount;
}
+ /* Store the count of successfully parsed tags */
+ n->count = tcount;
}
static unsigned int
case sanyoV1:
case epsonV1:
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
+ return;
+ }
/* Write the header and the number of entries. */
strcpy ((char *)*buf, n->version==sanyoV1?"SANYO":
case olympusV2:
*buf_size += 8-6 + 4;
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
+ return;
+ }
/* Write the header and the number of entries. */
strcpy ((char *)*buf, "OLYMPUS");
*buf_size += 8 + 2;
*buf_size += 4; /* Next IFD pointer */
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size);
+ return;
+ }
/* Write the header and the number of entries. */
strcpy ((char *)*buf, "Nikon");
ts = *buf_size + s;
t = exif_mem_realloc (ne->mem, *buf,
sizeof (char) * ts);
- if (!t) return;
+ if (!t) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts);
+ return;
+ }
*buf = t;
*buf_size = ts;
exif_set_long (*buf + o, n->order, datao + doff);
{
ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en;
ExifShort c;
- size_t i, tcount, s, o, o2 = 0, datao = 6, base = 0;
-
- if (!n || !buf) return;
+ size_t i, tcount, o, o2 = 6 + n->offset, /* Start of interesting data */
+ datao = 6, base = 0;
- /* Start of interesting data */
- o2 = 6 + n->offset;
+ if (!n || !buf || !buf_size || (n->offset + 22 < n->offset) ||
+ (n->offset + 22 < 22) || (n->offset + 22 > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataOlympus", "Short MakerNote");
+ return;
+ }
/*
* Olympus headers start with "OLYMP" and need to have at least
* two unknown bytes (0), "MM" or "II", another byte 0 and
* lastly 0x2A.
*/
- if (buf_size - n->offset < 22) return;
if (!memcmp (buf + o2, "OLYMP", 6) || !memcmp (buf + o2, "SANYO", 6) ||
!memcmp (buf + o2, "EPSON", 6)) {
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
else if (buf[o2 + 6 + 1] == 1)
n->order = EXIF_BYTE_ORDER_MOTOROLA;
o2 += 8;
- if (o2 >= buf_size) return;
+ if (o2 + 2 > buf_size) return;
c = exif_get_short (buf + o2, n->order);
if ((!(c & 0xFF)) && (c > 0x500)) {
if (n->order == EXIF_BYTE_ORDER_INTEL) {
base = MNOTE_NIKON1_TAG_BASE;
/* Fix endianness, if needed */
- if (o2 >= buf_size) return;
+ if (o2 + 2 > buf_size) return;
c = exif_get_short (buf + o2, n->order);
if ((!(c & 0xFF)) && (c > 0x500)) {
if (n->order == EXIF_BYTE_ORDER_INTEL) {
o2 += 2;
/* Go to where the number of entries is. */
- if (o2 >= buf_size) return;
+ if (o2 + 4 > buf_size) return;
o2 = datao + exif_get_long (buf + o2, n->order);
break;
return;
}
- /* Number of entries */
- if (o2 >= buf_size) return;
+ /* Sanity check the offset */
+ if ((o2 + 2 < o2) || (o2 + 2 < 2) || (o2 + 2 > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteOlympus", "Short MakerNote");
+ return;
+ }
+
+ /* Read the number of tags */
c = exif_get_short (buf + o2, n->order);
o2 += 2;
- /* Read the number of entries and remove old ones. */
+ /* Remove any old entries */
exif_mnote_data_olympus_clear (n);
+ /* Reserve enough space for all the possible MakerNote tags */
n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c);
- if (!n->entries) return;
+ if (!n->entries) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c);
+ return;
+ }
/* Parse all c entries, storing ones that are successfully parsed */
- for (i = c, tcount = 0, o = o2; i; --i, o += 12) {
- size_t dataofs;
- if ((o + 12 < o) || (o + 12 < 12) || (o + 12 > buf_size)) {
+ 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)) {
exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifMnoteOlympus", "Short MakerNote");
break;
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
"Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
mnote_olympus_tag_get_name (n->entries[tcount].tag));
- exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
+/* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus",
"0x%x %d %ld*(%d)",
n->entries[tcount].tag,
n->entries[tcount].format,
n->entries[tcount].components,
- (int)exif_format_get_size(n->entries[tcount].format));
+ (int)exif_format_get_size(n->entries[tcount].format)); */
/*
* Size? If bigger than 4 bytes, the actual data is not
n->entries[tcount].components;
n->entries[tcount].size = s;
if (s) {
- dataofs = o + 8;
+ 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) + datao;
#ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG
/* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when
continue;
}
- /* Sanity check */
n->entries[tcount].data = exif_mem_alloc (en->mem, s);
- if (!n->entries[tcount].data) continue;
+ if (!n->entries[tcount].data) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s);
+ continue;
+ }
memcpy (n->entries[tcount].data, buf + dataofs, s);
}
case casioV2:
base = MNOTE_PENTAX2_TAG_BASE;
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
-
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
+ return;
+ }
/* Write the magic header */
strcpy ((char *)*buf, "QVC");
exif_set_short (*buf + 4, n->order, (ExifShort) 0);
case pentaxV3:
base = MNOTE_PENTAX2_TAG_BASE;
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
+ return;
+ }
/* Write the magic header */
strcpy ((char *)*buf, "AOC");
case pentaxV2:
base = MNOTE_PENTAX2_TAG_BASE;
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
+ return;
+ }
/* Write the magic header */
strcpy ((char *)*buf, "AOC");
*buf_size -= 6;
o2 -= 6;
*buf = exif_mem_alloc (ne->mem, *buf_size);
- if (!*buf) return;
+ if (!*buf) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", *buf_size);
+ return;
+ }
break;
default:
doff = *buf_size;
t = exif_mem_realloc (ne->mem, *buf,
sizeof (char) * ts);
- if (!t) return;
+ if (!t) {
+ EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataPentax", ts);
+ return;
+ }
*buf = t;
*buf_size = ts;
exif_set_long (*buf + o, n->order, datao + doff);
const unsigned char *buf, unsigned int buf_size)
{
ExifMnoteDataPentax *n = (ExifMnoteDataPentax *) en;
- size_t i, o, s, datao = 6 + n->offset, base = 0;
+ size_t i, tcount, o, datao = 6 + n->offset, base = 0;
ExifShort c;
- /* Number of entries */
- if (buf_size < datao + (4 + 2) + 2) return;
+ if (!n || !buf || !buf_size || (datao + 8 < datao) ||
+ (datao + 8 < 8) || (datao + 8 > buf_size)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataPentax", "Short MakerNote");
+ return;
+ }
+
+ /* Detect varient of Pentax/Casio MakerNote found */
if (!memcmp(buf + datao, "AOC", 4)) {
if ((buf[datao + 4] == 'I') && (buf[datao + 5] == 'I')) {
n->version = pentaxV3;
"Parsing Pentax maker note v1...");
n->version = pentaxV1;
}
+
+ /* Read the number of tags */
c = exif_get_short (buf + datao, n->order);
+ datao += 2;
+
+ /* Remove any old entries */
+ exif_mnote_data_pentax_clear (n);
+
+ /* Reserve enough space for all the possible MakerNote tags */
n->entries = exif_mem_alloc (en->mem, sizeof (MnotePentaxEntry) * c);
- if (!n->entries) return;
+ if (!n->entries) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", sizeof (MnotePentaxEntry) * c);
+ return;
+ }
- for (i = 0; i < c; i++) {
- o = datao + 2 + 12 * i;
- if (o + 8 > buf_size) {
+ /* 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)) {
exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifMnoteDataPentax", "Short MakerNote");
- return;
+ break;
}
- n->count = i + 1;
- n->entries[i].tag = exif_get_short (buf + o + 0, n->order) + base;
- 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;
+ n->entries[tcount].tag = exif_get_short (buf + o + 0, n->order) + base;
+ 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 (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnotePentax",
- "Loading entry 0x%x ('%s')...", n->entries[i].tag,
- mnote_pentax_tag_get_name (n->entries[i].tag));
+ "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
+ mnote_pentax_tag_get_name (n->entries[tcount].tag));
/*
* 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 > 65536) {
- /* Corrupt data: EXIF data size is limited to the
- * maximum size of a JPEG segment (64 kb).
- */
- continue;
- }
- if (!s) return;
- o += 8;
- if (s > 4) o = exif_get_long (buf + o, n->order) + 6;
- if ((o + s < o) || (o + s < s) || (o + s > buf_size)) {
- exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
- "ExifMnoteDataPentax", "Tag data past end "
- "of buffer (%u > %u)", o + s, buf_size);
- return;
+ s = exif_format_get_size (n->entries[tcount].format) *
+ n->entries[tcount].components;
+ n->entries[tcount].size = s;
+ 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)) {
+ exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
+ "ExifMnoteDataPentax", "Tag data past end "
+ "of buffer (%u > %u)", dataofs + s, buf_size);
+ continue;
+ }
+
+ n->entries[tcount].data = exif_mem_alloc (en->mem, s);
+ if (!n->entries[tcount].data) {
+ EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataPentax", s);
+ continue;
+ }
+ memcpy (n->entries[tcount].data, buf + dataofs, s);
}
-
- /* Sanity check */
- n->entries[i].data = exif_mem_alloc (en->mem, s);
- if (!n->entries[i].data) return;
- n->entries[i].size = s;
- memcpy (n->entries[i].data, buf + o, s);
- }
+
+ /* Tag was successfully parsed */
+ ++tcount;
+ }
+ /* Store the count of successfully parsed tags */
+ n->count = tcount;
}
static unsigned int