*/
/*#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);
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;
else if (buf[o2 + 6 + 1] == 1)
n->order = EXIF_BYTE_ORDER_MOTOROLA;
o2 += 8;
- 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) {
/* Olympus S760, S770 */
datao = o2;
o2 += 8;
+ 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], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
+ buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I'))
n->order = EXIF_BYTE_ORDER_INTEL;
case nikonV1:
o2 += 6;
- if (o2 >= buf_size) return;
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
"Parsing Nikon maker note v1 (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]);
+ "%02x)...",
+ buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]);
/* Skip version number */
o2 += 1;
base = MNOTE_NIKON1_TAG_BASE;
/* Fix endianness, if needed */
- 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) {
case nikonV2:
o2 += 6;
- if (o2 >= 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 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3],
buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]);
/* Skip version number */
* gets calculated.
*/
datao = o2;
- if (o2 >= buf_size) return;
if (!strncmp ((char *)&buf[o2], "II", 2))
n->order = EXIF_BYTE_ORDER_INTEL;
else if (!strncmp ((char *)&buf[o2], "MM", 2))
o2 += 2;
/* Go to where the number of entries is. */
- if (o2 + 4 > buf_size) return;
o2 = datao + exif_get_long (buf + o2, n->order);
break;
/* 00 1b is # of entries in Motorola order - the rest should also be in MM order */
n->order = EXIF_BYTE_ORDER_MOTOROLA;
break;
-
+
default:
exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus",
"Unknown Olympus variant %i.", n->version);
}
/* 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;
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;
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).
* 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,
}
#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)",
- dataofs + s, buf_size);
+ (unsigned)(dataofs + s), buf_size);
continue;
}
o_orig = n->order;
n->order = o;
for (i = 0; i < n->count; i++) {
+ if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
+ continue;
n->entries[i].order = o;
exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
n->entries[i].components, o_orig, o);