| Index: libexif/sources/libexif/exif-data.c
|
| ===================================================================
|
| --- libexif/sources/libexif/exif-data.c (revision 143189)
|
| +++ libexif/sources/libexif/exif-data.c (working copy)
|
| @@ -781,15 +781,15 @@
|
|
|
| void
|
| exif_data_load_data (ExifData *data, const unsigned char *d_orig,
|
| - unsigned int ds_orig)
|
| + unsigned int ds)
|
| {
|
| unsigned int l;
|
| ExifLong offset;
|
| ExifShort n;
|
| const unsigned char *d = d_orig;
|
| - unsigned int ds = ds_orig, len;
|
| + unsigned int len, fullds;
|
|
|
| - if (!data || !data->priv || !d || !ds)
|
| + if (!data || !data->priv || !d || !ds)
|
| return;
|
|
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| @@ -807,21 +807,21 @@
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| "Found EXIF header.");
|
| } else {
|
| - while (1) {
|
| - while ((d[0] == 0xff) && ds) {
|
| + while (ds >= 3) {
|
| + while (ds && (d[0] == 0xff)) {
|
| d++;
|
| ds--;
|
| }
|
|
|
| /* JPEG_MARKER_SOI */
|
| - if (d[0] == JPEG_MARKER_SOI) {
|
| + if (ds && d[0] == JPEG_MARKER_SOI) {
|
| d++;
|
| ds--;
|
| continue;
|
| }
|
|
|
| /* JPEG_MARKER_APP0 */
|
| - if (d[0] == JPEG_MARKER_APP0) {
|
| + if (ds >= 3 && d[0] == JPEG_MARKER_APP0) {
|
| d++;
|
| ds--;
|
| l = (d[0] << 8) | d[1];
|
| @@ -833,7 +833,7 @@
|
| }
|
|
|
| /* JPEG_MARKER_APP1 */
|
| - if (d[0] == JPEG_MARKER_APP1)
|
| + if (ds && d[0] == JPEG_MARKER_APP1)
|
| break;
|
|
|
| /* Unknown marker or data. Give up. */
|
| @@ -841,12 +841,12 @@
|
| "ExifData", _("EXIF marker not found."));
|
| return;
|
| }
|
| - d++;
|
| - ds--;
|
| - if (ds < 2) {
|
| + if (ds < 3) {
|
| LOG_TOO_SMALL;
|
| return;
|
| }
|
| + d++;
|
| + ds--;
|
| len = (d[0] << 8) | d[1];
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| "We have to deal with %i byte(s) of EXIF data.",
|
| @@ -872,9 +872,18 @@
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| "Found EXIF header.");
|
|
|
| - /* Byte order (offset 6, length 2) */
|
| + /* Sanity check the data length */
|
| if (ds < 14)
|
| return;
|
| +
|
| + /* The JPEG APP1 section can be no longer than 64 KiB (including a
|
| + 16-bit length), so cap the data length to protect against overflow
|
| + in future offset calculations */
|
| + fullds = ds;
|
| + if (ds > 0xfffe)
|
| + ds = 0xfffe;
|
| +
|
| + /* Byte order (offset 6, length 2) */
|
| if (!memcmp (d + 6, "II", 2))
|
| data->priv->order = EXIF_BYTE_ORDER_INTEL;
|
| else if (!memcmp (d + 6, "MM", 2))
|
| @@ -894,24 +903,25 @@
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| "IFD 0 at %i.", (int) offset);
|
|
|
| + /* Sanity check the offset, being careful about overflow */
|
| + if (offset > ds || offset + 6 + 2 > ds)
|
| + return;
|
| +
|
| /* Parse the actual exif data (usually offset 14 from start) */
|
| exif_data_load_data_content (data, EXIF_IFD_0, d + 6, ds - 6, offset, 0);
|
|
|
| /* IFD 1 offset */
|
| - if (offset + 6 + 2 > ds) {
|
| - return;
|
| - }
|
| n = exif_get_short (d + 6 + offset, data->priv->order);
|
| - if (offset + 6 + 2 + 12 * n + 4 > ds) {
|
| + if (offset + 6 + 2 + 12 * n + 4 > ds)
|
| return;
|
| - }
|
| +
|
| offset = exif_get_long (d + 6 + offset + 2 + 12 * n, data->priv->order);
|
| if (offset) {
|
| exif_log (data->priv->log, EXIF_LOG_CODE_DEBUG, "ExifData",
|
| "IFD 1 at %i.", (int) offset);
|
|
|
| /* Sanity check. */
|
| - if (offset > ds - 6) {
|
| + if (offset > ds || offset + 6 > ds) {
|
| exif_log (data->priv->log, EXIF_LOG_CODE_CORRUPT_DATA,
|
| "ExifData", "Bogus offset of IFD1.");
|
| } else {
|
| @@ -925,7 +935,7 @@
|
| * space between IFDs. Here is the only place where we have access
|
| * to that data.
|
| */
|
| - interpret_maker_note(data, d, ds);
|
| + interpret_maker_note(data, d, fullds);
|
|
|
| /* Fixup tags if requested */
|
| if (data->priv->options & EXIF_DATA_OPTION_FOLLOW_SPECIFICATION)
|
|
|