Update of /cvsroot/libexif/libexif/libexif
In directory vz-cvs-4.sog:/tmp/cvs-serv18066/libexif

Modified Files:
	exif-entry.c 
Log Message:
Fixed some buffer overflows in exif_entry_format_value()
This fixes CVE-2012-2814


Index: libexif/exif-entry.c
===================================================================
--- libexif/exif-entry.c.orig
+++ libexif/exif-entry.c
@@ -586,8 +586,8 @@ exif_entry_get_value (ExifEntry *e, char
 	ExifSLong v_slong;
 	ExifRational v_rat;
 	ExifSRational v_srat;
-	char b[64];
 	const char *c;
+	size_t len;
 	ExifByteOrder o;
 	double d;
 	ExifEntry *entry;
@@ -761,12 +761,10 @@ exif_entry_get_value (ExifEntry *e, char
 		v_rat = exif_get_rational (e->data, o);
 		if (!v_rat.denominator) return val;
 		d = (double) v_rat.numerator / (double) v_rat.denominator;
-		snprintf (val, maxlen, _("%.02lf EV"), d);
-		snprintf (b, sizeof (b), _(" (f/%.01f)"), pow (2, d / 2.));
-		if (maxlen > strlen (val) + strlen (b))
-			strncat (val, b, maxlen - strlen (val) - 1);
+		snprintf (val, maxlen, _("%.02lf EV (f/%.01f)"), d, pow (2, d / 2.));
 		break;
-	case EXIF_TAG_FOCAL_LENGTH:
+	case EXIF_TAG_FOCAL_LENGTH: {
+		char b[64];
 		CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
 		CC (e, 1, val, maxlen);
 		v_rat = exif_get_rational (e->data, o);
@@ -802,6 +800,7 @@ exif_entry_get_value (ExifEntry *e, char
 		if (maxlen > strlen (val) + strlen (b))
 			strncat (val, b, maxlen - strlen (val) - 1);
 		break;
+	}
 	case EXIF_TAG_SUBJECT_DISTANCE:
 		CF (e, EXIF_FORMAT_RATIONAL, val, maxlen);
 		CC (e, 1, val, maxlen);
@@ -823,7 +822,9 @@ exif_entry_get_value (ExifEntry *e, char
 		if (maxlen > strlen (val) + strlen (_(" sec.")))
 			strncat (val, _(" sec."), maxlen - strlen (val) - 1);
 		break;
-	case EXIF_TAG_SHUTTER_SPEED_VALUE:
+	case EXIF_TAG_SHUTTER_SPEED_VALUE: {
+		char b[64];
+
 		CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
 		CC (e, 1, val, maxlen);
 		v_srat = exif_get_srational (e->data, o);
@@ -843,7 +844,10 @@ exif_entry_get_value (ExifEntry *e, char
       strncat (val, b, maxlen - strlen (val) - 1);
     }
 		break;
-	case EXIF_TAG_BRIGHTNESS_VALUE:
+	}
+	case EXIF_TAG_BRIGHTNESS_VALUE: {
+		char b[64];
+
 		CF (e, EXIF_FORMAT_SRATIONAL, val, maxlen);
 		CC (e, 1, val, maxlen);
 		v_srat = exif_get_srational (e->data, o);
@@ -855,6 +859,7 @@ exif_entry_get_value (ExifEntry *e, char
 		if (maxlen > strlen (val) + strlen (b))
 			strncat (val, b, maxlen - strlen (val) - 1);
 		break;
+	}
 	case EXIF_TAG_FILE_SOURCE:
 		CF (e, EXIF_FORMAT_UNDEFINED, val, maxlen);
 		CC (e, 1, val, maxlen);
@@ -1038,7 +1043,8 @@ exif_entry_get_value (ExifEntry *e, char
 		}
 		/* Fall through - EXIF_TAG_GPS_LATITUDE is same as INTEROPERABILITY_VERSION */
 	default:
-		if (!e->size) break;
+		if (!e->size || !maxlen) break;
+		++maxlen; /* include the terminating NUL */
 		switch (e->format) {
 		case EXIF_FORMAT_UNDEFINED:
 			if ((e->tag == EXIF_TAG_SCENE_TYPE) && (e->size == 1)) {
@@ -1052,64 +1058,61 @@ exif_entry_get_value (ExifEntry *e, char
 		case EXIF_FORMAT_SBYTE:
 			v_byte = e->data[0];
 			snprintf (val, maxlen, "0x%02x", v_byte);
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_byte = e->data[i];
-				snprintf (b, sizeof (b), ", 0x%02x", v_byte);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed)maxlen <= 0) break;
+				snprintf (val+len, maxlen-len, ", 0x%02x", v_byte);
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_SHORT:
 		case EXIF_FORMAT_SSHORT:
 			v_short = exif_get_short (e->data, o);
 			snprintf (val, maxlen, "%i", v_short);
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_short = exif_get_short (e->data +
 					exif_format_get_size (e->format) *
 					i, o);
-				snprintf (b, sizeof (b), ", %i", v_short);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed)maxlen <= 0) break;
+				snprintf (val+len, maxlen-len, ", %i", v_short);
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_LONG:
 			v_long = exif_get_long (e->data, o);
 			snprintf (val, maxlen, "%li", (long int) v_long);
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_long = exif_get_long (e->data +
 					exif_format_get_size (e->format) *
 					i, o);
-				snprintf (b, sizeof (b), ", %li",
+				snprintf (val+len, maxlen-len, ", %li",
 					(long int) v_long);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed)maxlen <= 0) break;
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_SLONG:
 			v_slong = exif_get_slong (e->data, o);
 			snprintf (val, maxlen, "%li", (long int) v_slong);
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_long = exif_get_slong (e->data +
 					exif_format_get_size (e->format) *
 					i, o);
-				snprintf (b, sizeof (b), ", %li",
+				snprintf (val+len, maxlen-len, ", %li",
 						(long int) v_long);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed)maxlen <= 0) break;
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_ASCII:
-			strncpy (val, (char *) e->data, MIN (maxlen, e->size));
+			strncpy (val, (char *) e->data, MIN (maxlen-1, e->size));
 			break;
 		case EXIF_FORMAT_RATIONAL:
+			len = 0;
 			v_rat = exif_get_rational (e->data, o);
 			if (v_rat.denominator)
 				snprintf (val, maxlen, "%2.2lf",
@@ -1119,21 +1122,20 @@ exif_entry_get_value (ExifEntry *e, char
 				snprintf (val, maxlen, "%2.2lf/%2.2lf",
 				          (double) v_rat.numerator,
 					  (double) v_rat.denominator);
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_rat = exif_get_rational (
 					e->data + 8 * i, o);
 				if (v_rat.denominator)
-					snprintf (b, sizeof (b), ", %2.2lf",
+					snprintf (val+len, maxlen-len, ", %2.2lf",
 					          (double) v_rat.numerator /
 					          (double) v_rat.denominator);
 				else
-					snprintf (b, sizeof (b), ", %2.2lf/%2.2lf",
+					snprintf (val+len, maxlen-len, ", %2.2lf/%2.2lf",
 					          (double) v_rat.numerator,
 						  (double) v_rat.denominator);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed) maxlen <= 0) break;
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_SRATIONAL:
@@ -1143,15 +1145,14 @@ exif_entry_get_value (ExifEntry *e, char
 			} else {
 				snprintf (val, maxlen, "%i/%i", v_srat.numerator,  v_srat.denominator);
 			}
-			maxlen -= strlen (val);
+			len = strlen (val);
 			for (i = 1; i < e->components; i++) {
 				v_srat = exif_get_srational (
 					e->data + 8 * i, o);
-				snprintf (b, sizeof (b), ", %2.2f",
+				snprintf (val+len, maxlen-len, ", %2.2f",
 					  (double)v_srat.numerator / v_srat.denominator);
-				strncat (val, b, maxlen);
-				maxlen -= strlen (b);
-				if ((signed) maxlen <= 0) break;
+				len += strlen (val+len);
+				if (len >= maxlen-1) break;
 			}
 			break;
 		case EXIF_FORMAT_DOUBLE:
