gnumeric r16509 - in branches/gnumeric-1-6: debian plugins/excel



Author: jdassen
Date: Sat Apr 12 09:11:16 2008
New Revision: 16509
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16509&view=rev

Log:
Backported fix for CVE-2008-0668 [#505330]

Modified:
   branches/gnumeric-1-6/debian/changelog
   branches/gnumeric-1-6/plugins/excel/ChangeLog
   branches/gnumeric-1-6/plugins/excel/ms-excel-read.c

Modified: branches/gnumeric-1-6/debian/changelog
==============================================================================
--- branches/gnumeric-1-6/debian/changelog	(original)
+++ branches/gnumeric-1-6/debian/changelog	Sat Apr 12 09:11:16 2008
@@ -1,3 +1,12 @@
+gnumeric (1.6.3-5.1+etch1) stable-security; urgency=high
+
+  * Non-maintainer upload by the Security Team.
+  * Backport fix from upstream SVN:
+    - CVE-2008-0668: arbitrary code execution through integer overflow in
+      Excel spreadsheet HLINK handling
+
+ -- Devin Carraway <devin debian org>  Sun, 30 Mar 2008 01:02:31 +0000
+
 gnumeric (1.6.3-6) unstable; urgency=low
 
   * [plugins/excel/ms-chart.c] Don't delete a valid axis. Pulled in from

Modified: branches/gnumeric-1-6/plugins/excel/ms-excel-read.c
==============================================================================
--- branches/gnumeric-1-6/plugins/excel/ms-excel-read.c	(original)
+++ branches/gnumeric-1-6/plugins/excel/ms-excel-read.c	Sat Apr 12 09:11:16 2008
@@ -95,6 +95,45 @@
 
 #define N_BYTES_BETWEEN_PROGRESS_UPDATES   0x1000
 
+/*
+ * Check whether the product of the first two arguments exceeds
+ * the third.  The function should be overflow-proof.
+ */
+static gboolean
+product_gt (size_t count, size_t itemsize, size_t space)
+{
+       return itemsize > 0 &&
+               (count > G_MAXUINT / itemsize || count * itemsize > space);
+}
+
+static void
+record_size_barf (size_t count, size_t itemsize, size_t space,
+                 const char *locus)
+{
+       g_warning ("File is most likely corrupted.\n"
+                  "(Requested %u*%u bytes, but only %u bytes left in record.\n"
+                  "The problem occurred in %s.)",
+                  (unsigned)count, (unsigned)itemsize,
+                  (unsigned)space,
+                  locus);
+}
+
+#define XL_NEED_BYTES(count) XL_NEED_ITEMS(count,1)
+
+#define XL_NEED_ITEMS(count__,size__)                                  \
+  do {                                                                 \
+         size_t count_ = (count__);                                    \
+         size_t size_ = (size__);                                      \
+         size_t space_ = q->length - (data - q->data);                 \
+         if (G_UNLIKELY (product_gt (count_, size_, space_))) {        \
+                record_size_barf (count_, size_, space_, G_STRFUNC);   \
+               return;                                                 \
+          }                                                            \
+  } while (0)
+
+
+
+
 /* #define NO_DEBUG_EXCEL */
 #ifndef NO_DEBUG_EXCEL
 #define d(level, code)	do { if (ms_excel_read_debug > level) { code } } while (0)
@@ -3386,28 +3425,40 @@
 			continue;
 
 		for (data = q->data + 4; ep.eval.col <= last_col ; ep.eval.col++) {
-			g_return_if_fail (data + 1 - q->data <= (int)q->length);
+			guint8 oper;
+			XL_NEED_BYTES (1);
 
-			switch (*data) {
-			case  1: v = value_new_float (GSF_LE_GET_DOUBLE (data+1));
-				 data += 9;
-				 break;
-			case  2: len = data[1];
-				 v = value_new_string_nocopy (
-					excel_get_text (importer, data + 2, len, NULL));
-				 data += 2 + len;
-				 break;
-
-			case  4: v = value_new_bool (GSF_LE_GET_GUINT16 (data+1) != 0);
-				 data += 9;
-				 break;
-
-			case 16: v = biff_get_error (&ep, GSF_LE_GET_GUINT16 (data+1));
-				 data += 9;
-				 break;
+                       oper = *data++;
+                       switch (oper) {
+                       case  1:
+                               XL_NEED_BYTES (8);
+                               v = value_new_float (GSF_LE_GET_DOUBLE (data));
+                               data += 8;
+                               break;
+                       case  2:
+                               XL_NEED_BYTES (1);
+                               len = *data++;
+                               v = value_new_string_nocopy (
+                                       excel_get_text (importer, data, len, NULL));
+                               data += len;
+                               break;
+
+                       case 4:
+                               XL_NEED_BYTES (2);
+                               v = value_new_bool (GSF_LE_GET_GUINT16 (data) != 0);
+                               /* FIXME: 8?? */
+                               data += 8;
+                               break;
+
+                       case 16:
+                               XL_NEED_BYTES (2);
+                               v = biff_get_error (&ep, GSF_LE_GET_GUINT16 (data));
+                               /* FIXME: 8?? */
+                               data += 8;
+                               break;
 
 			default :
-				g_warning ("Unknown oper type 0x%x in a CRN record", (int)*data);
+				g_warning ("Unknown oper type 0x%x in a CRN record", oper);
 				data++;
 				v = NULL;
 			}
@@ -4933,7 +4984,7 @@
 	if ((options & 0x14) == 0x14) {
 		len = GSF_LE_GET_GUINT32 (data);
 		data += 4;
-		g_return_if_fail (data + len*2 - q->data <= (int)q->length);
+		XL_NEED_ITEMS (len, 2);
 		label = read_utf16_str (len, data);
 		data += len*2;
 	}
@@ -4942,7 +4993,7 @@
 	if (options & 0x80) {
 		len = GSF_LE_GET_GUINT32 (data);
 		data += 4;
-		g_return_if_fail (len*2 + data - q->data <= (int)q->length);
+		XL_NEED_ITEMS (len, 2);
 		target = read_utf16_str (len, data);
 		data += len*2;
 	}
@@ -4953,8 +5004,8 @@
 		data += sizeof (url_guid);
 		len = GSF_LE_GET_GUINT32 (data);
 		data += 4;
-		g_return_if_fail (len + data - q->data <= (int)q->length);
 
+		XL_NEED_BYTES (len);
 		url = read_utf16_str (len/2, data);
 		link = g_object_new (gnm_hlink_url_get_type (), NULL);
 		gnm_hlink_set_target (link, url);
@@ -4966,6 +5017,7 @@
 		len = GSF_LE_GET_GUINT32 (data + 2);
 		fprintf (stderr,"up count %hu len %hx\n", GSF_LE_GET_GUINT16 (data), len);
 		data += 6;
+		XL_NEED_BYTES (len);
 
 		gsf_mem_dump (data, q->length - (data - q->data));
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]