avoid the use of unsafe integer overflow checking constructs (unsigned integer operations cannot overflow, so "u1 + u2 > u1" can be optimized away)
check for the actual sizes, which should also handle the overflows
document other places google patched, but do not seem relevant due to other restrictions
fixes https://github.com/libexif/libexif/issues/26
doff = offset + 8;
/* Sanity checks */
doff = offset + 8;
/* Sanity checks */
- if ((doff + s < doff) || (doff + s < s) || (doff + s > size)) {
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
- "Tag data past end of buffer (%u > %u)", doff+s, size);
+ "Tag starts past end of buffer (%u > %u)", doff, size);
+ return 0;
+ }
+
+ if (s > size - doff) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
+ "Tag data goes past end of buffer (%u > %u)", doff+s, size);
unsigned int ds, ExifLong o, ExifLong s)
{
/* Sanity checks */
unsigned int ds, ExifLong o, ExifLong s)
{
/* Sanity checks */
- if ((o + s < o) || (o + s < s) || (o + s > ds) || (o > ds)) {
- exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
- "Bogus thumbnail offset (%u) or size (%u).",
- o, s);
+ if (o >= ds) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail offset (%u).", o);
+ return;
+ }
+ if (s > ds - o) {
+ exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData", "Bogus thumbnail size (%u), max would be %u.", s, ds-o);
if (data->data)
exif_mem_free (data->priv->mem, data->data);
if (!(data->data = exif_data_alloc (data, s))) {
if (data->data)
exif_mem_free (data->priv->mem, data->data);
if (!(data->data = exif_data_alloc (data, s))) {
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
"IFD 0 at %i.", (int) offset);
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
"IFD 0 at %i.", (int) offset);
- /* Sanity check the offset, being careful about overflow */
+ /* ds is restricted to 16 bit above, so offset is restricted too, and offset+8 should not overflow. */
if (offset > ds || offset + 6 + 2 > ds)
return;
if (offset > ds || offset + 6 + 2 > ds)
return;
/* IFD 1 offset */
n = exif_get_short (d + 6 + offset, data->priv->order);
/* IFD 1 offset */
n = exif_get_short (d + 6 + offset, data->priv->order);
+ /* offset < 2<<16, n is 16 bit at most, so this op will not overflow */
if (offset + 6 + 2 + 12 * n + 4 > ds)
return;
if (offset + 6 + 2 + 12 * n + 4 > ds)
return;
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
"IFD 1 at %i.", (int) offset);
exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
"IFD 1 at %i.", (int) offset);
- /* Sanity check. */
- if (offset > ds || offset + 6 > ds) {
+ /* Sanity check. ds is ensured to be above 6 above, offset is 16bit */
+ if (offset > ds - 6) {
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifData", "Bogus offset of IFD1.");
} else {
exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
"ExifData", "Bogus offset of IFD1.");
} else {