Description: Fix security issue CVE-2012-2812
Author: Dan Fandrich <dan@coneharvesters.com>
Origin: backport
Bug-Debian: http://bugs.debian.org/681454
Applied-Upstream: 0.6.21
Forwarded: not-needed
Last-Update: 2012-07-17
--- a/libexif/exif-entry.c
+++ b/libexif/exif-entry.c
@@ -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;
@@ -947,9 +970,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);
@@ -958,15 +981,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));
 
