From: Dan F. <dfa...@us...> - 2012-07-12 17:13:07
|
Update of /cvsroot/libexif/libexif/libexif In directory vz-cvs-4.sog:/tmp/cvs-serv18224/libexif Modified Files: exif-entry.c Log Message: Fixed an out of bounds read on corrupted input. The EXIF_TAG_COPYRIGHT tag ought to be, but perhaps is not, NUL-terminated. This fixes CVE-2012-2812 Index: exif-entry.c =================================================================== RCS file: /cvsroot/libexif/libexif/libexif/exif-entry.c,v retrieving revision 1.147 retrieving revision 1.148 diff -u -d -r1.147 -r1.148 --- exif-entry.c 12 Jul 2012 17:12:24 -0000 1.147 +++ exif-entry.c 12 Jul 2012 17:13:03 -0000 1.148 @@ -611,6 +611,30 @@ 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 +830,6 @@ 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; @@ -948,9 +971,9 @@ /* * 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))) + if (e->size && e->data && match_repeated_char(e->data, ' ', e->size)) strncpy (val, (char *) e->data, MIN (maxlen, e->size)); else strncpy (val, _("[None]"), maxlen); @@ -959,15 +982,20 @@ /* Second part: Editor. */ strncat (val, " - ", maxlen - 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++) { + int editor_ofs = tagdata - e->data; + int remaining = e->size - editor_ofs; + if (match_repeated_char(tagdata, ' ', remaining)) { + strncat (val, (const char*)tagdata, MIN (maxlen - strlen (val), remaining)); + ++k; + } + } } + if (!k) + strncat (val, _("[None]"), maxlen - strlen (val)); strncat (val, " ", maxlen - strlen (val)); strncat (val, _("(Editor)"), maxlen - strlen (val)); |