Fixed a couple of compiler warnings.
[platform/upstream/libexif.git] / libexif / exif-entry.c
index becf1f1..61260d3 100644 (file)
@@ -166,6 +166,13 @@ exif_entry_free (ExifEntry *e)
        }
 }
 
+static void
+clear_entry (ExifEntry *e)
+{
+       e->components = 0;
+       e->size = 0;
+}
+
 /*! Get a value and convert it to an ExifShort.
  * \bug Not all types are converted that could be converted and no indication
  *      is made when that occurs
@@ -367,8 +374,7 @@ exif_entry_fix (ExifEntry *e)
                if (e->size < 8) {
                        e->data = exif_entry_realloc (e, e->data, 8 + e->size);
                        if (!e->data) {
-                               e->size = 0;
-                               e->components = 0;
+                               clear_entry(e);
                                return;
                        }
 
@@ -410,8 +416,7 @@ exif_entry_fix (ExifEntry *e)
                    memcmp (e->data, "\0\0\0\0\0\0\0\0", 8)) {
                        e->data = exif_entry_realloc (e, e->data, 8 + e->size);
                        if (!e->data) {
-                               e->size = 0;
-                               e->components = 0;
+                               clear_entry(e);
                                break;
                        }
 
@@ -438,7 +443,7 @@ exif_entry_fix (ExifEntry *e)
  * \pre The ExifEntry is already a member of an ExifData.
  * \param[in] e EXIF entry
  * \param[out] val buffer in which to store value
- * \param[in] maxlen one less than the length of the buffer val
+ * \param[in] maxlen the length of the buffer val
  */
 static void
 exif_entry_format_value(ExifEntry *e, char *val, size_t maxlen)
@@ -456,7 +461,6 @@ exif_entry_format_value(ExifEntry *e, char *val, size_t maxlen)
 
        if (!e->size || !maxlen)
                return;
-       ++maxlen; /* include the terminating NUL */
        switch (e->format) {
        case EXIF_FORMAT_UNDEFINED:
                snprintf (val, maxlen, _("%i bytes undefined data"), e->size);
@@ -566,7 +570,7 @@ exif_entry_format_value(ExifEntry *e, char *val, size_t maxlen)
                        v_srat = exif_get_srational (
                                e->data + 8 * i, o);
                        if (v_srat.denominator) {
-                               int decimals = (int)(log10(fabs(v_srat.denominator))-0.08+1.0);
+                               int decimals = (int)(log10(abs(v_srat.denominator))-0.08+1.0);
                                snprintf (val+len, maxlen-len, "%2.*f",
                                          decimals,
                                          (double) v_srat.numerator /
@@ -611,6 +615,30 @@ exif_entry_dump (ExifEntry *e, unsigned int indent)
        printf ("%s  Value: %s\n", buf, exif_entry_get_value (e, value, sizeof(value)));
 }
 
+/*! Check if a string consists entirely of a single, repeated character.
+ * Up to first n bytes are checked.
+ * 
+ * \param[in] data pointer of string to check
+ * \param[in] ch character to match
+ * \param[in] n maximum number of characters to match
+ *
+ * \return 0 if the string matches or is of zero length, nonzero otherwise
+ */
+static int
+match_repeated_char(const unsigned char *data, unsigned char ch, size_t n)
+{
+       int i;
+       for (i=n; i; --i, ++data) {
+               if (*data == 0) {
+                       i = 0;  /* all bytes before NUL matched */
+                       break;
+               }
+               if (*data != ch)
+                       break;
+       }
+       return i;
+}
+
 #define CF(entry,target,v,maxlen)                                      \
 {                                                                      \
        if (entry->format != target) {                                  \
@@ -806,7 +834,6 @@ const char *
 exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
 {
        unsigned int i, j, k;
-       const unsigned char *t;
        ExifShort v_short, v_short2, v_short3, v_short4;
        ExifByte v_byte;
        ExifRational v_rat;
@@ -830,23 +857,17 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                {""    , 0,  0}
        };
 
-       /* FIXME: This belongs to somewhere else. */
-       /* libexif should use the default system locale.
-        * If an application specifically requires UTF-8, then we
-        * must give the application a way to tell libexif that.
-        * 
-        * bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-        */
-       bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+       (void) bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+
+       if (!e || !e->parent || !e->parent->parent || !maxlen || !val)
+               return val;
 
        /* make sure the returned string is zero terminated */
+       /* FIXME: this is inefficient in the case of long buffers and should
+        * instead be taken care of on each write instead. */
        memset (val, 0, maxlen);
-       maxlen--;
-       memset (b, 0, sizeof (b));
 
        /* We need the byte order */
-       if (!e || !e->parent || !e->parent->parent)
-               return val;
        o = exif_data_get_byte_order (e->parent->parent);
 
        /* Sanity check */
@@ -880,11 +901,11 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                 * NULL terminated.
                 */
                if ((e->size >= 8) && !memcmp (e->data, "ASCII\0\0\0", 8)) {
-                       strncpy (val, (char *) e->data + 8, MIN (e->size - 8, maxlen));
+                       strncpy (val, (char *) e->data + 8, MIN (e->size - 8, maxlen-1));
                        break;
                }
                if ((e->size >= 8) && !memcmp (e->data, "UNICODE\0", 8)) {
-                       strncpy (val, _("Unsupported UNICODE string"), maxlen);
+                       strncpy (val, _("Unsupported UNICODE string"), maxlen-1);
                /* FIXME: use iconv to convert into the locale encoding.
                 * EXIF 2.2 implies (but does not say) that this encoding is
                 * UCS-2.
@@ -892,7 +913,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                        break;
                }
                if ((e->size >= 8) && !memcmp (e->data, "JIS\0\0\0\0\0", 8)) {
-                       strncpy (val, _("Unsupported JIS string"), maxlen);
+                       strncpy (val, _("Unsupported JIS string"), maxlen-1);
                /* FIXME: use iconv to convert into the locale encoding */
                        break;
                }
@@ -904,24 +925,24 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
 
                /*
                 * If we reach this point, the tag does not
-                * comply with the standard and seems to contain data.
+                * comply with the standard but seems to contain data.
                 * Print as much as possible.
+                * Note: make sure we do not overwrite the final \0 at maxlen-1
                 */
                exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
                        _("Tag UserComment contains data but is "
                          "against specification."));
-               for (; (i < e->size)  && (strlen (val) < maxlen - 1); i++) {
+               for (j = 0; (i < e->size) && (j < maxlen-1); i++, j++) {
                        exif_entry_log (e, EXIF_LOG_CODE_DEBUG,
                                _("Byte at position %i: 0x%02x"), i, e->data[i]);
-                       val[strlen (val)] =
-                               isprint (e->data[i]) ? e->data[i] : '.';
+                       val[j] = isprint (e->data[i]) ? e->data[i] : '.';
                }
                break;
 
        case EXIF_TAG_EXIF_VERSION:
                CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
                CC (e, 4, val, maxlen);
-               strncpy (val, _("Unknown Exif Version"), maxlen);
+               strncpy (val, _("Unknown Exif Version"), maxlen-1);
                for (i = 0; *versions[i].label; i++) {
                        if (!memcmp (e->data, versions[i].label, 4)) {
                                snprintf (val, maxlen,
@@ -936,11 +957,11 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
                CC (e, 4, val, maxlen);
                if (!memcmp (e->data, "0100", 4))
-                       strncpy (val, _("FlashPix Version 1.0"), maxlen);
+                       strncpy (val, _("FlashPix Version 1.0"), maxlen-1);
                else if (!memcmp (e->data, "0101", 4))
-                       strncpy (val, _("FlashPix Version 1.01"), maxlen);
+                       strncpy (val, _("FlashPix Version 1.01"), maxlen-1);
                else
-                       strncpy (val, _("Unknown FlashPix Version"), maxlen);
+                       strncpy (val, _("Unknown FlashPix Version"), maxlen-1);
                break;
        case EXIF_TAG_COPYRIGHT:
                CF (e, EXIF_FORMAT_ASCII, val, maxlen);
@@ -948,28 +969,33 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                /*
                 * First part: Photographer.
                 * Some cameras store a string like "   " here. Ignore it.
+                * Remember that a corrupted tag might not be NUL-terminated
                 */
-               if (e->size && e->data &&
-                   (strspn ((char *)e->data, " ") != strlen ((char *) e->data)))
-                       strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+               if (e->size && e->data && match_repeated_char(e->data, ' ', e->size))
+                       strncpy (val, (char *) e->data, MIN (maxlen-1, e->size));
                else
-                       strncpy (val, _("[None]"), maxlen);
-               strncat (val, " ", maxlen - strlen (val));
-               strncat (val, _("(Photographer)"), maxlen - strlen (val));
+                       strncpy (val, _("[None]"), maxlen-1);
+               strncat (val, " ", maxlen-1 - strlen (val));
+               strncat (val, _("(Photographer)"), maxlen-1 - strlen (val));
 
                /* Second part: Editor. */
-               strncat (val, " - ", maxlen - strlen (val));
+               strncat (val, " - ", maxlen-1 - strlen (val));
+               k = 0;
                if (e->size && e->data) {
-                       size_t ts;
-                       t = e->data + strlen ((char *) e->data) + 1;
-                       ts = e->data + e->size - t;
-                       if ((ts > 0) && (strspn ((char *)t, " ") != ts))
-                               strncat (val, (char *)t, MIN (maxlen - strlen (val), ts));
-               } else {
-                       strncat (val, _("[None]"), maxlen - strlen (val));
+                       const unsigned char *tagdata = memchr(e->data, 0, e->size);
+                       if (tagdata++) {
+                               unsigned int editor_ofs = tagdata - e->data;
+                               unsigned int remaining = e->size - editor_ofs;
+                               if (match_repeated_char(tagdata, ' ', remaining)) {
+                                       strncat (val, (const char*)tagdata, MIN (maxlen-1 - strlen (val), remaining));
+                                       ++k;
+                               }
+                       }
                }
-               strncat (val, " ", maxlen - strlen (val));
-               strncat (val, _("(Editor)"), maxlen - strlen (val));
+               if (!k)
+                       strncat (val, _("[None]"), maxlen-1 - strlen (val));
+               strncat (val, " ", maxlen-1 - strlen (val));
+               strncat (val, _("(Editor)"), maxlen-1 - strlen (val));
 
                break;
        case EXIF_TAG_FNUMBER:
@@ -995,8 +1021,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                d = (double) v_rat.numerator / (double) v_rat.denominator;
                snprintf (val, maxlen, _("%.02f EV"), d);
                snprintf (b, sizeof (b), _(" (f/%.01f)"), pow (2, d / 2.));
-               if (maxlen > strlen (val) + strlen (b))
-                       strncat (val, b, maxlen - strlen (val));
+               strncat (val, b, maxlen-1 - strlen (val));
                break;
        case EXIF_TAG_FOCAL_LENGTH:
                CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
@@ -1028,14 +1053,15 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                        }
                }
                if (d)
-                       snprintf (b, sizeof (b), _(" (35 equivalent: %d mm)"),
-                                 (int) (d * (double) v_rat.numerator /
-                                            (double) v_rat.denominator));
+                       snprintf (b, sizeof (b), _(" (35 equivalent: %.0f mm)"),
+                                 (d * (double) v_rat.numerator /
+                                      (double) v_rat.denominator));
+               else
+                       b[0] = 0;
 
                d = (double) v_rat.numerator / (double) v_rat.denominator;
                snprintf (val, maxlen, "%.1f mm", d);
-               if (maxlen > strlen (val) + strlen (b))
-                       strncat (val, b, maxlen - strlen (val));
+               strncat (val, b, maxlen-1 - strlen (val));
                break;
        case EXIF_TAG_SUBJECT_DISTANCE:
                CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
@@ -1058,11 +1084,10 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                }
                d = (double) v_rat.numerator / (double) v_rat.denominator;
                if (d < 1)
-                       snprintf (val, maxlen, _("1/%i"), (int) (0.5 + 1. / d));
+                       snprintf (val, maxlen, _("1/%.0f"), 1. / d);
                else
-                       snprintf (val, maxlen, "%i", (int) d);
-               if (maxlen > strlen (val) + strlen (_(" sec.")))
-                       strncat (val, _(" sec."), maxlen - strlen (val));
+                       snprintf (val, maxlen, "%.0f", d);
+               strncat (val, _(" sec."), maxlen-1 - strlen (val));
                break;
        case EXIF_TAG_SHUTTER_SPEED_VALUE:
                CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
@@ -1076,10 +1101,10 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                snprintf (val, maxlen, _("%.02f EV"), d);
                d = 1. / pow (2, d);
                if (d < 1)
-                 snprintf (b, sizeof (b), _(" (1/%d sec.)"), (int) (1. / d));
+                 snprintf (b, sizeof (b), _(" (1/%.0f sec.)"), 1. / d);
                else
-                 snprintf (b, sizeof (b), _(" (%d sec.)"), (int) d);
-               strncat (val, b, maxlen - strlen (val));
+                 snprintf (b, sizeof (b), _(" (%.0f sec.)"), d);
+               strncat (val, b, maxlen-1 - strlen (val));
                break;
        case EXIF_TAG_BRIGHTNESS_VALUE:
                CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
@@ -1093,15 +1118,14 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                snprintf (val, maxlen, _("%.02f EV"), d);
                snprintf (b, sizeof (b), _(" (%.02f cd/m^2)"),
                        1. / (M_PI * 0.3048 * 0.3048) * pow (2, d));
-               if (maxlen > strlen (val) + strlen (b))
-                       strncat (val, b, maxlen - strlen (val));
+               strncat (val, b, maxlen-1 - strlen (val));
                break;
        case EXIF_TAG_FILE_SOURCE:
                CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
                CC (e, 1, val, maxlen);
                v_byte = e->data[0];
                if (v_byte == 3)
-                       strncpy (val, _("DSC"), maxlen);
+                       strncpy (val, _("DSC"), maxlen-1);
                else
                        snprintf (val, maxlen, _("Internal error (unknown "
                                  "value %i)"), v_byte);
@@ -1120,9 +1144,9 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                        case 6: c = _("B"); break;
                        default: c = _("Reserved"); break;
                        }
-                       strncat (val, c, maxlen - strlen (val));
+                       strncat (val, c, maxlen-1 - strlen (val));
                        if (i < 3)
-                               strncat (val, " ", maxlen - strlen (val));
+                               strncat (val, " ", maxlen-1 - strlen (val));
                }
                break;
        case EXIF_TAG_EXPOSURE_BIAS_VALUE:
@@ -1141,7 +1165,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                CC (e, 1, val, maxlen);
                v_byte = e->data[0];
                if (v_byte == 1)
-                       strncpy (val, _("Directly photographed"), maxlen);
+                       strncpy (val, _("Directly photographed"), maxlen-1);
                else
                        snprintf (val, maxlen, _("Internal error (unknown "
                                  "value %i)"), v_byte);
@@ -1154,9 +1178,9 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                        e->data + exif_format_get_size (e->format),
                        o);
                if ((v_short == 2) && (v_short2 == 1))
-                       strncpy (val, _("YCbCr4:2:2"), maxlen);
+                       strncpy (val, _("YCbCr4:2:2"), maxlen-1);
                else if ((v_short == 2) && (v_short2 == 2))
-                       strncpy (val, _("YCbCr4:2:0"), maxlen);
+                       strncpy (val, _("YCbCr4:2:0"), maxlen-1);
                else
                        snprintf (val, maxlen, "%u, %u", v_short, v_short2);
                break;
@@ -1199,20 +1223,17 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                CC (e, 4, val, maxlen);
                v_byte = e->data[0];
                snprintf (val, maxlen, "%u", v_byte);
-               maxlen -= strlen (val);
                for (i = 1; i < e->components; i++) {
                        v_byte = e->data[i];
                        snprintf (b, sizeof (b), ".%u", v_byte);
-                       strncat (val, b, maxlen);
-                       maxlen -= strlen (b);
-                       if ((signed)maxlen <= 0) break;
+                       strncat (val, b, maxlen-1 - strlen (val));
                }
                break;
        case EXIF_TAG_INTEROPERABILITY_VERSION:
        /* a.k.a. case EXIF_TAG_GPS_LATITUDE: */
                /* This tag occurs in EXIF_IFD_INTEROPERABILITY */
                if (e->format == EXIF_FORMAT_UNDEFINED) {
-                       strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+                       strncpy (val, (char *) e->data, MIN (maxlen-1, e->size));
                        break;
                }
                /* EXIF_TAG_GPS_LATITUDE is the same numerically as
@@ -1226,9 +1247,9 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                CC (e, 1, val, maxlen);
                v_byte = e->data[0];
                if (v_byte == 0)
-                       strncpy (val, _("Sea level"), maxlen);
+                       strncpy (val, _("Sea level"), maxlen-1);
                else if (v_byte == 1)
-                       strncpy (val, _("Sea level reference"), maxlen);
+                       strncpy (val, _("Sea level reference"), maxlen-1);
                else
                        snprintf (val, maxlen, _("Internal error (unknown "
                                  "value %i)"), v_byte);
@@ -1300,7 +1321,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                for (k = 0; list2[i].elem[j].values[k]; k++) {
                        size_t l = strlen (_(list2[i].elem[j].values[k]));
                        if ((maxlen > l) && (strlen (val) < l))
-                               strncpy (val, _(list2[i].elem[j].values[k]), maxlen);
+                               strncpy (val, _(list2[i].elem[j].values[k]), maxlen-1);
                }
                if (!val[0]) snprintf (val, maxlen, "%i", v_short);
 
@@ -1338,7 +1359,7 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
                else if (!*list[i].strings[j])
                        snprintf (val, maxlen, _("Unknown value %i"), v_short);
                else
-                       strncpy (val, _(list[i].strings[j]), maxlen);
+                       strncpy (val, _(list[i].strings[j]), maxlen-1);
                break;
 
        case EXIF_TAG_XP_TITLE:
@@ -1346,10 +1367,29 @@ exif_entry_get_value (ExifEntry *e, char *val, unsigned int maxlen)
        case EXIF_TAG_XP_AUTHOR:
        case EXIF_TAG_XP_KEYWORDS:
        case EXIF_TAG_XP_SUBJECT:
+       {
+               unsigned short *utf16;
+
+               /* Sanity check the size to prevent overflow */
+               if (e->size+sizeof(unsigned short) < e->size) break;
+
+               /* The tag may not be U+0000-terminated , so make a local
+                  U+0000-terminated copy before converting it */
+               utf16 = exif_mem_alloc (e->priv->mem, e->size+sizeof(unsigned short));
+               if (!utf16) break;
+               memcpy(utf16, e->data, e->size);
+
+               /* NUL terminate the string. If the size is odd (which isn't possible
+                * for a UTF16 string), then this will overwrite the final garbage byte.
+                */
+               utf16[e->size/sizeof(unsigned short)] = 0;
+
                /* Warning! The texts are converted from UTF16 to UTF8 */
                /* FIXME: use iconv to convert into the locale encoding */
-               exif_convert_utf16_to_utf8(val, (unsigned short*)e->data, MIN(maxlen, e->size));
+               exif_convert_utf16_to_utf8(val, utf16, maxlen);
+               exif_mem_free(e->priv->mem, utf16);
                break;
+       }
 
        default:
                /* Use a generic value formatting */
@@ -1389,7 +1429,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_LONG;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                break;
 
        /* SHORT, 1 component, no default */
@@ -1420,7 +1460,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 0);
                break;
 
@@ -1432,7 +1472,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 1);
                break;
 
@@ -1443,7 +1483,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 2);
                break;
 
@@ -1453,7 +1493,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 3);
                break;
 
@@ -1463,7 +1503,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 0xffff);
                break;
 
@@ -1473,7 +1513,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 8);
                exif_set_short (
                        e->data + exif_format_get_size (e->format),
@@ -1489,7 +1529,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SHORT;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                exif_set_short (e->data, o, 2);
                exif_set_short (
                        e->data + exif_format_get_size (e->format),
@@ -1504,7 +1544,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_SRATIONAL;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                break;
 
        /* RATIONAL, 1 component, no default */
@@ -1525,7 +1565,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_RATIONAL;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                break;
 
        /* RATIONAL, 1 component, default 72/1 */
@@ -1535,7 +1575,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_RATIONAL;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                r.numerator = 72;
                r.denominator = 1;
                exif_set_rational (e->data, o, r);
@@ -1547,7 +1587,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_RATIONAL;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                break;
 
        /* RATIONAL, 6 components */
@@ -1556,7 +1596,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_RATIONAL;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                r.denominator = 1;
                r.numerator = 0;
                exif_set_rational (e->data, o, r);
@@ -1598,7 +1638,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_ASCII;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                snprintf ((char *) e->data, e->size,
                          "%04i:%02i:%02i %02i:%02i:%02i",
                          tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
@@ -1626,7 +1666,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_ASCII;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                strncpy ((char *)e->data, _("[None]"), e->size);
                break;
        /* ASCII, default "[None]\0[None]\0" */
@@ -1635,7 +1675,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_ASCII;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                strcpy (((char *)e->data) + 0, _("[None]"));
                strcpy (((char *)e->data) + strlen (_("[None]")) + 1, _("[None]"));
                break;
@@ -1646,7 +1686,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_UNDEFINED;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                e->data[0] = 0x01;
                break;
 
@@ -1656,7 +1696,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                e->format = EXIF_FORMAT_UNDEFINED;
                e->size = exif_format_get_size (e->format) * e->components;
                e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+               if (!e->data) { clear_entry(e); break; }
                e->data[0] = 0x03;
                break;
 
@@ -1666,7 +1706,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                 e->format = EXIF_FORMAT_UNDEFINED;
                 e->size = exif_format_get_size (e->format) * e->components;
                 e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+                if (!e->data) { clear_entry(e); break; }
                 memcpy (e->data, "0100", 4);
                 break;
 
@@ -1676,7 +1716,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                 e->format = EXIF_FORMAT_UNDEFINED;
                 e->size = exif_format_get_size (e->format) * e->components;
                 e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+                if (!e->data) { clear_entry(e); break; }
                 memcpy (e->data, "0210", 4);
                 break;
 
@@ -1686,7 +1726,7 @@ exif_entry_initialize (ExifEntry *e, ExifTag tag)
                 e->format = EXIF_FORMAT_UNDEFINED;
                 e->size = exif_format_get_size (e->format) * e->components;
                 e->data = exif_entry_alloc (e, e->size);
-               if (!e->data) break;
+                if (!e->data) { clear_entry(e); break; }
                e->data[0] = 1;
                e->data[1] = 2;
                e->data[2] = 3;