gnumeric r16355 - in trunk: . plugins/excel



Author: mortenw
Date: Thu Feb  7 23:27:12 2008
New Revision: 16355
URL: http://svn.gnome.org/viewvc/gnumeric?rev=16355&view=rev

Log:
2008-02-07  Morten Welinder  <terra gnome org>

	* ms-chart.c (xl_chart_import_error_bar): Avoid crash in missing
	parent-series case.  Fixes #514630.

	* ms-formula-read.c (excel_parse_formula1, excel_parse_formula):
	Grow a maxlen argument and make sure we do not read more.  Fixes
	#514637.

	* ms-excel-read.c (excel_read_string_header, excel_get_text): Grow
	an array_length argument and make sure we do not read more array
	data than call.  All callers changed.
	(excel_biff_text, excel_biff_text_1, excel_biff_text_2): New
	Biff-record based wrappers for excel_get_text.
	(excel_formula_shared): Make sure to copy the data behind the
	expression too.



Modified:
   trunk/NEWS
   trunk/plugins/excel/ChangeLog
   trunk/plugins/excel/ms-chart.c
   trunk/plugins/excel/ms-excel-read.c
   trunk/plugins/excel/ms-excel-read.h
   trunk/plugins/excel/ms-formula-read.c
   trunk/plugins/excel/ms-formula-read.h
   trunk/plugins/excel/ms-obj.c
   trunk/plugins/excel/ms-pivot.c

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Thu Feb  7 23:27:12 2008
@@ -22,7 +22,7 @@
 	* Fix corrupted-xls-file problems.  [#512984] [#513005] [#513313]
 	  [#513317] [#513361] [#513364] [#513551] [#513605] [#513608] [#513790]
 	  [#513787] [#513835] [#513963] [#514229] [#514230] [#514295] [#514435]
-	  [#514436] [#514437] [#514506] [#514510]
+	  [#514436] [#514437] [#514506] [#514510] [#514630] [#514637]
 	* Fix non-ascii export problem.  [#511135]
 	* Band-aid evaluation problem with broken xls.  [#513559]
 	* Fix circular array formula problem.

Modified: trunk/plugins/excel/ms-chart.c
==============================================================================
--- trunk/plugins/excel/ms-chart.c	(original)
+++ trunk/plugins/excel/ms-chart.c	Thu Feb  7 23:27:12 2008
@@ -1902,7 +1902,7 @@
 	if (slen == 0)
 		return FALSE;
 
-	str = excel_get_text (s->container.importer, q->data + 3, slen, NULL);
+	str = excel_biff_text_1 (s->container.importer, q, 2);
 	d (2, g_printerr ("'%s';\n", str););
 
 	if (s->currentSeries != NULL &&
@@ -3010,7 +3010,8 @@
 chart_parse_expr  (MSContainer *container, guint8 const *data, int length)
 {
 	return excel_parse_formula (container, NULL, 0, 0,
-				    data, length, FALSE, NULL);
+				    data, length, 0 /* FIXME? */,
+				    FALSE, NULL);
 }
 
 static Sheet *
@@ -3108,10 +3109,13 @@
 	GogMSDimType msdim;
 	char const *prop_name = (series->err_type < 3)
 		? "x-errors" : "y-errors";
-	GParamSpec *pspec = g_object_class_find_property (
+	GParamSpec *pspec;
+
+	XL_CHECK_CONDITION (parent->series != NULL);
+
+	pspec = g_object_class_find_property (
 		G_OBJECT_GET_CLASS (parent->series),
 		prop_name);
-
 	state->plot = parent->series->plot;
 	if (pspec == NULL) {
 		pspec = g_object_class_find_property (
@@ -3131,8 +3135,8 @@
 		GOData	      *data;
 
 		g_object_get (G_OBJECT (parent->series),
-						prop_name, &error_bar,
-						NULL);
+			      prop_name, &error_bar,
+			      NULL);
 		if (!error_bar) {
 			error_bar = g_object_new (GOG_ERROR_BAR_TYPE, NULL);
 			error_bar->display = GOG_ERROR_BAR_DISPLAY_NONE;
@@ -3237,15 +3241,14 @@
 static void
 ms_excel_chart_read_LABEL (BiffQuery *q, XLChartReadState *state)
 {
-	guint16 row, sernum, len;
+	guint16 row, sernum;
 	char *label;
 	XLChartSeries *series;
 
-	XL_CHECK_CONDITION (q->length >= 8);
+	XL_CHECK_CONDITION (q->length >= 6);
 	row = GSF_LE_GET_GUINT16 (q->data + 0);
 	sernum = GSF_LE_GET_GUINT16 (q->data + 2);
 	/* xf  = GSF_LE_GET_GUINT16 (q->data + 4); */
-	len = GSF_LE_GET_GUINT16 (q->data + 6);
 
 	if (state->cur_role < 0 ||
 	    state->series == NULL ||
@@ -3253,7 +3256,7 @@
 	    NULL == (series = g_ptr_array_index (state->series, sernum)))
 		return;
 
-	label = excel_get_text (state->container.importer, q->data + 8, len, NULL);
+	label = excel_biff_text_2 (state->container.importer, q, 6);
 	if (label != NULL  &&
 	    series->data[state->cur_role].value != NULL) {
 		value_release (series->data[state->cur_role].value->vals[0][row]);

Modified: trunk/plugins/excel/ms-excel-read.c
==============================================================================
--- trunk/plugins/excel/ms-excel-read.c	(original)
+++ trunk/plugins/excel/ms-excel-read.c	Thu Feb  7 23:27:12 2008
@@ -289,7 +289,8 @@
 	g_return_val_if_fail (length > 0, NULL);
 
 	texpr = excel_parse_formula (&esheet->container, esheet, 0, 0,
-		data, length, FALSE, NULL);
+				     data, length, 0 /* FIXME */,
+				     FALSE, NULL);
 	if (ms_excel_read_debug > 8) {
 		char *tmp;
 		GnmParsePos pp;
@@ -825,52 +826,68 @@
 
 /**
  * excel_read_string_header :
- * @ptr : a pointer to the start of the string header
+ * @data : a pointer to the start of the string header
+ * @maxlen : the length of the data area
  * @use_utf16 : Is the content in 8 or 16 bit chars
  * @n_markup : number of trailing markup records
  * @has_extended : Is there trailing extended string info (eg japanese PHONETIC)
  * @post_data_len :
  *
- * returns a pointer to the start of the string
+ * returns the length of the header (in bytes)
  **/
-static unsigned
-excel_read_string_header (guint8 const *data,
+static guint32
+excel_read_string_header (guint8 const *data, guint32 maxlen,
 			  gboolean *use_utf16,
 			  unsigned *n_markup,
 			  gboolean *has_extended,
-			  unsigned  *post_data_len)
+			  unsigned *post_data_len)
 {
-	guint8 header = GSF_LE_GET_GUINT8 (data);
-	guint8 const *ptr = data;
+	guint8 header;
+	guint32 len;
 
-	*post_data_len = 0;
+	if (G_UNLIKELY (maxlen < 1))
+		goto error;
 
-	/* be anal and double check that the header looks valid */
-	if (((header & 0xf2) == 0)) {
-		*use_utf16  = (header & 0x1) != 0;
-
-		ptr++; /* skip header */
-		if ((header & 0x8) != 0) {
-			*n_markup = GSF_LE_GET_GUINT16 (ptr);
-			*post_data_len += *n_markup * 4; /* 4 bytes per */
-			ptr += 2;
-		} else
-			*n_markup = 0;
-		if ((*has_extended   = (header & 0x4) != 0)) {
-			guint32 len_ext_rst = GSF_LE_GET_GUINT32 (ptr); /* A byte length */
-			*post_data_len += len_ext_rst;
-			ptr += 4;
-
-			g_warning ("extended string support unimplemented:"
-				   "ignoring %u bytes\n", len_ext_rst);
-		}
+	header = GSF_LE_GET_GUINT8 (data);
+	if (((header & 0xf2) != 0))
+		goto error;
+
+	*use_utf16 = (header & 0x1) != 0;
+
+	if ((header & 0x8) != 0) {
+		if (G_UNLIKELY (maxlen < 3))
+			goto error;
+		*n_markup = GSF_LE_GET_GUINT16 (data + 1);
+		*post_data_len = *n_markup * 4; /* 4 bytes per */
+		len = 3;
 	} else {
-		g_warning ("potential problem.  A string with an invalid header was found");
-		*use_utf16 = *has_extended = FALSE;
 		*n_markup = 0;
+		*post_data_len = 0;
+		len = 1;
+	}
+
+	*has_extended = (header & 0x4) != 0;
+	if (*has_extended) {
+		guint32 len_ext_rst;
+
+		if (G_UNLIKELY (maxlen < len + 4))
+			goto error;
+		len_ext_rst = GSF_LE_GET_GUINT32 (data + len); /* A byte length */
+		*post_data_len += len_ext_rst;
+		len += 4;
+
+		g_warning ("Extended string support unimplemented; "
+			   "ignoring %u bytes\n", len_ext_rst);
 	}
 
-	return ptr - data;
+	return len;
+
+ error:
+	*use_utf16 = *has_extended = FALSE;
+	*n_markup = 0;
+	*post_data_len = 0;
+	g_warning ("Invalid string record.");
+	return 0;
 }
 
 char *
@@ -902,10 +919,10 @@
 	return ans;
 }
 
-static char *
-excel_get_text_full (GnmXLImporter const *importer,
-		     guint8 const *pos, guint32 length,
-		     guint32 *byte_length, guint32 maxlen)
+char *
+excel_get_text (GnmXLImporter const *importer,
+		guint8 const *pos, guint32 length,
+		guint32 *byte_length, guint32 maxlen)
 {
 	char *ans;
 	guint8 const *ptr;
@@ -919,8 +936,10 @@
 		*byte_length = 1; /* the header */
 		if (length == 0)
 			return NULL;
-		ptr = pos + excel_read_string_header (pos,
-			&use_utf16, &n_markup, &has_extended, &trailing_data_len);
+		ptr = pos + excel_read_string_header
+			(pos, maxlen,
+			 &use_utf16, &n_markup, &has_extended,
+			 &trailing_data_len);
 		*byte_length += trailing_data_len;
 	} else {
 		*byte_length = 0; /* no header */
@@ -957,7 +976,7 @@
 }
 
 /**
- * excel_get_text :
+ * excel_get_text_fixme :
  * @importer :
  * @pos : pointer to the start of string information
  * @length : in _characters_
@@ -965,12 +984,12 @@
  *
  * Returns a string which the caller is responsible for freeing
  **/
-char *
-excel_get_text (GnmXLImporter const *importer,
-		guint8 const *pos, guint32 length, guint32 *byte_length)
+static char *
+excel_get_text_fixme (GnmXLImporter const *importer,
+		      guint8 const *pos, guint32 length, guint32 *byte_length)
 {
-	return excel_get_text_full (importer, pos, length, byte_length,
-				    G_MAXUINT);
+	return excel_get_text (importer, pos, length, byte_length,
+					  G_MAXUINT);
 }
 
 static char *
@@ -979,11 +998,11 @@
 {
 	XL_CHECK_CONDITION_VAL (q->length >= ofs, NULL);
 
-	return excel_get_text_full (importer, q->data + ofs, length,
+	return excel_get_text (importer, q->data + ofs, length,
 				    NULL, q->length - ofs);
 }
 
-static char *
+char *
 excel_biff_text_1 (GnmXLImporter const *importer,
 		   const BiffQuery *q, guint32 ofs)
 {
@@ -993,11 +1012,11 @@
 	length = GSF_LE_GET_GUINT8 (q->data + ofs);
 	ofs++;
 
-	return excel_get_text_full (importer, q->data + ofs, length,
+	return excel_get_text (importer, q->data + ofs, length,
 				    NULL, q->length - ofs);
 }
 
-static char *
+char *
 excel_biff_text_2 (GnmXLImporter const *importer,
 		   const BiffQuery *q, guint32 ofs)
 {
@@ -1007,8 +1026,8 @@
 	length = GSF_LE_GET_GUINT16 (q->data + ofs);
 	ofs += 2;
 
-	return excel_get_text_full (importer, q->data + ofs, length,
-				    NULL, q->length - ofs);
+	return excel_get_text (importer, q->data + ofs, length,
+			       NULL, q->length - ofs);
 }
 
 typedef struct {
@@ -1098,9 +1117,10 @@
 	offset += 2;
 	do {
 		offset = ms_biff_query_bound_check (q, offset, 1);
-		offset += excel_read_string_header (q->data + offset,
-				&use_utf16, &n_markup, &has_extended,
-				&post_data_len);
+		offset += excel_read_string_header
+			(q->data + offset, q->length - offset,
+			 &use_utf16, &n_markup, &has_extended,
+			 &post_data_len);
 		total_end_len += post_data_len;
 		total_n_markup += n_markup;
 		chars_left = (q->length - offset) / (use_utf16 ? 2 : 1);
@@ -2403,8 +2423,8 @@
 static GnmExprTop const *
 excel_formula_shared (BiffQuery *q, ExcelReadSheet *esheet, GnmCell *cell)
 {
-	guint16 opcode, data_len;
-	GnmRange   r;
+	guint16 opcode, data_len, data_ofs, array_data_len;
+	GnmRange r;
 	gboolean is_array;
 	GnmExprTop const *texpr;
 	guint8 const *data;
@@ -2420,6 +2440,7 @@
 	}
 	ms_biff_query_next (q);
 
+	XL_CHECK_CONDITION_VAL (q->length >= 6, NULL);
 	r.start.row	= GSF_LE_GET_GUINT16 (q->data + 0);
 	r.end.row	= GSF_LE_GET_GUINT16 (q->data + 2);
 	r.start.col	= GSF_LE_GET_GUINT8 (q->data + 4);
@@ -2467,15 +2488,17 @@
 
 	is_array = (q->opcode != BIFF_SHRFMLA);
 
-	if (esheet_ver (esheet) > MS_BIFF_V4) {
-		data = q->data + (is_array ? 14 : 10);
-		data_len = GSF_LE_GET_GUINT16 (q->data + (is_array ? 12 : 8));
-	} else {
-		data = q->data + 10;
-		data_len = GSF_LE_GET_GUINT16 (q->data + 8);
-	}
+	data_ofs = (esheet_ver (esheet) > MS_BIFF_V4 && is_array) ? 14 : 10;
+	XL_CHECK_CONDITION_VAL (q->length >= data_ofs, NULL);
+	data = q->data + data_ofs;
+	data_len = GSF_LE_GET_GUINT16 (q->data + (data_ofs - 2));
+	XL_CHECK_CONDITION_VAL (q->length >= data_ofs + data_len, NULL);
+	array_data_len = data_len > 0 ? q->length - (data_ofs + data_len) : 0;
+
 	texpr = excel_parse_formula (&esheet->container, esheet,
-		r.start.col, r.start.row, data, data_len, !is_array, NULL);
+				     r.start.col, r.start.row,
+				     data, data_len, array_data_len,
+				     !is_array, NULL);
 
 	sf = g_new (XLSharedFormula, 1);
 
@@ -2486,8 +2509,9 @@
 	 */
 	sf->key = cell->pos;
 	sf->is_array = is_array;
-	sf->data = data_len > 0 ? g_memdup (data, data_len) : NULL;
+	sf->data = data_len > 0 ? g_memdup (data, data_len + array_data_len) : NULL;
 	sf->data_len = data_len;
+	sf->array_data_len = array_data_len;
 
 	d (1, fprintf (stderr,"Shared formula, extent %s\n", range_as_string (&r)););
 
@@ -2546,31 +2570,20 @@
 	 * and have this checking done there.
 	 */
 	if (esheet_ver (esheet) >= MS_BIFF_V5) {
+		XL_CHECK_CONDITION (q->length >= 22);
 		expr_length = GSF_LE_GET_GUINT16 (q->data + 20);
 		offset = 22;
 	} else if (esheet_ver (esheet) >= MS_BIFF_V3) {
+		XL_CHECK_CONDITION (q->length >= 18);
 		expr_length = GSF_LE_GET_GUINT16 (q->data + 16);
 		offset = 18;
 	} else {
+		XL_CHECK_CONDITION (q->length >= 17);
 		expr_length = GSF_LE_GET_GUINT8 (q->data + 16);
 		offset = 17;
 		val_dat++;	/* compensate for the 3 byte style */
 	}
-
-	if (q->length < offset) {
-		g_printerr ("FIXME: serious formula error: "
-			"invalid FORMULA (0x%x) record with length %d (should >= %d)\n",
-			q->opcode, q->length, offset);
-		gnm_cell_set_value (cell, value_new_error (NULL, "Formula Error"));
-		return;
-	}
-	if (q->length < (unsigned)(offset + expr_length)) {
-		g_printerr ("FIXME: serious formula error: "
-			"supposed length 0x%x, real len 0x%x\n",
-                        expr_length, q->length - offset);
-		gnm_cell_set_value (cell, value_new_error (NULL, "Formula Error"));
-		return;
-	}
+	XL_CHECK_CONDITION (q->length >= offset + expr_length);
 
 	/* Get the current value so that we can format, do this BEFORE handling
 	 * shared/array formulas or strings in case we need to go to the next
@@ -2594,7 +2607,9 @@
 	}
 
 	texpr = excel_parse_formula (&esheet->container, esheet, col, row,
-		(q->data + offset), expr_length, FALSE, &array_elem);
+				     q->data + offset, expr_length,
+				     q->length - (offset + expr_length),
+				     FALSE, &array_elem);
 #if 0
 	/* dump the trailing array and natural language data */
 	gsf_mem_dump (q->data + offset + expr_length,
@@ -2746,16 +2761,15 @@
 	XL_CHECK_CONDITION (pos.col < SHEET_MAX_COLS && pos.row < SHEET_MAX_ROWS);
 
 	if (esheet_ver (esheet) >= MS_BIFF_V8) {
-		guint16 options, obj_id, author_len;
+		guint16 options, obj_id;
 		gboolean hidden;
 		MSObj *obj;
 		char *author;
 
-		XL_CHECK_CONDITION (q->length >= 10);
+		XL_CHECK_CONDITION (q->length >= 8);
 		options = GSF_LE_GET_GUINT16 (q->data + 4);
 		hidden = (options & 0x2)==0;
 		obj_id = GSF_LE_GET_GUINT16 (q->data + 6);
-		author_len = GSF_LE_GET_GUINT16 (q->data + 8);
 
 		/* Docs claim that only 0x2 is valid, all other flags should
 		 * be 0 but we have seen examples with 0x100 'pusiuhendused juuli 2003.xls'
@@ -2766,7 +2780,7 @@
 		if (options & 0xe7d)
 			g_warning ("unknown flag on NOTE record %hx", options);
 
-		author = excel_biff_text (esheet->container.importer, q, 10, author_len);
+		author = excel_biff_text_2 (esheet->container.importer, q, 8);
 		d (1, fprintf (stderr,"Comment at %s%d id %d options"
 			      " 0x%x hidden %d by '%s'\n",
 			      col_name (pos.col), pos.row + 1,
@@ -3168,7 +3182,8 @@
 	if (expr_len != 0) {
 
 		texpr = excel_parse_formula (&importer->container, NULL, 0, 0,
-			expr_data, expr_len, TRUE, NULL);
+					     expr_data, expr_len, 0 /* FIXME? */,
+					     TRUE, NULL);
 
 		if (texpr == NULL) {
 			gnm_io_warning (importer->context, _("Failure parsing name '%s'"), name);
@@ -3220,9 +3235,10 @@
 			use_utf16 = has_extended = FALSE;
 			n_markup = trailing_data_len = 0;
 		} else
-			str += excel_read_string_header (str,
-				&use_utf16, &n_markup, &has_extended,
-				&trailing_data_len);
+			str += excel_read_string_header
+				(str, G_MAXINT /* FIXME */,
+				 &use_utf16, &n_markup, &has_extended,
+				 &trailing_data_len);
 
 		/* pull out the magic builtin enum */
 		builtin = excel_builtin_name (str);
@@ -3236,7 +3252,7 @@
 			name = g_strdup (builtin);
 		*name_len += str - data;
 	} else /* converts char len to byte len, and handles header */
-		name = excel_get_text (importer, data, *name_len, name_len);
+		name = excel_get_text_fixme (importer, data, *name_len, name_len);
 	return name;
 }
 
@@ -3491,13 +3507,13 @@
 		char *help_txt;
 		char *status_txt;
 
-		menu_txt = excel_get_text (importer, data, menu_txt_len, NULL);
+		menu_txt = excel_get_text_fixme (importer, data, menu_txt_len, NULL);
 		data += menu_txt_len;
-		descr_txt = excel_get_text (importer, data, descr_txt_len, NULL);
+		descr_txt = excel_get_text_fixme (importer, data, descr_txt_len, NULL);
 		data += descr_txt_len;
-		help_txt = excel_get_text (importer, data, help_txt_len, NULL);
+		help_txt = excel_get_text_fixme (importer, data, help_txt_len, NULL);
 		data += help_txt_len;
-		status_txt = excel_get_text (importer, data, status_txt_len, NULL);
+		status_txt = excel_get_text_fixme (importer, data, status_txt_len, NULL);
 
 		g_printerr ("Name record: '%s', '%s', '%s', '%s', '%s'\n",
 			name ? name : "(null)",
@@ -3588,7 +3604,7 @@
 				XL_NEED_BYTES (1);
 				len = *data++;
 				v = value_new_string_nocopy (
-					excel_get_text (importer, data, len, NULL));
+					excel_get_text_fixme (importer, data, len, NULL));
 				data += len;
 				break;
 
@@ -4956,22 +4972,22 @@
 	data = q->data + 4;
 
 	XL_CHECK_CONDITION (data+3 <= end);
-	input_title = excel_get_text (esheet->container.importer, data + 2,
+	input_title = excel_get_text_fixme (esheet->container.importer, data + 2,
 		GSF_LE_GET_GUINT16 (data), &len);
 	data += len + 2;
 
 	XL_CHECK_CONDITION (data+3 <= end);
-	error_title = excel_get_text (esheet->container.importer, data + 2,
+	error_title = excel_get_text_fixme (esheet->container.importer, data + 2,
 		GSF_LE_GET_GUINT16 (data), &len);
 	data += len + 2;
 
 	XL_CHECK_CONDITION (data+3 <= end);
-	input_msg = excel_get_text (esheet->container.importer, data + 2,
+	input_msg = excel_get_text_fixme (esheet->container.importer, data + 2,
 		GSF_LE_GET_GUINT16 (data), &len);
 	data += len + 2;
 
 	XL_CHECK_CONDITION (data+3 <= end);
-	error_msg = excel_get_text (esheet->container.importer, data + 2,
+	error_msg = excel_get_text_fixme (esheet->container.importer, data + 2,
 		GSF_LE_GET_GUINT16 (data), &len);
 	data += len + 2;
 
@@ -5058,13 +5074,15 @@
 
 	if (expr1_len > 0)
 		texpr1 = excel_parse_formula (&esheet->container, esheet,
-			col, row,
-			expr1_dat, expr1_len, TRUE, NULL);
+					      col, row,
+					      expr1_dat, expr1_len, 0 /* FIXME */,
+					      TRUE, NULL);
 
 	if (expr2_len > 0)
 		texpr2 = excel_parse_formula (&esheet->container, esheet,
-			col, row,
-			expr2_dat, expr2_len, TRUE, NULL);
+					      col, row,
+					      expr2_dat, expr2_len, 0 /* FIXME */,
+					      TRUE, NULL);
 
 	d (1, fprintf (stderr,"style = %d, type = %d, op = %d\n",
 		       style, type, op););
@@ -5450,12 +5468,12 @@
 		data = q->data + 24;
 		if (len0 > 0) {
 			v0 = value_new_string_nocopy (
-				excel_get_text (esheet->container.importer, data, len0, NULL));
+				excel_get_text_fixme (esheet->container.importer, data, len0, NULL));
 			data += len0;
 		}
 		if (len1 > 0)
 			v1 = value_new_string_nocopy (
-				excel_get_text (esheet->container.importer, data, len1, NULL));
+				excel_get_text_fixme (esheet->container.importer, data, len1, NULL));
 
 		if (op1 == GNM_FILTER_UNUSED) {
 			cond = gnm_filter_condition_new_single (op0, v0);
@@ -5741,7 +5759,7 @@
 		: GSF_LE_GET_GUINT16 (q->data + 6);
 	XL_CHECK_CONDITION (q->length - 8 >= in_len);
 
-	txt = excel_get_text (esheet->container.importer, q->data + 8,
+	txt = excel_get_text_fixme (esheet->container.importer, q->data + 8,
 		in_len, &str_len);
 
 	d (0, fprintf (stderr,"%s in %s;\n",
@@ -6345,7 +6363,7 @@
 	gsf_mem_dump (q->data + 4 + 1, len);
 	for (data = q->data + 4 + 1 + len, i = 0; i < numTabs ; i++) {
 		len = GSF_LE_GET_GUINT16 (data);
-		name = excel_get_text (importer, data + 2, len, &byte_length);
+		name = excel_get_text_fixme (importer, data + 2, len, &byte_length);
 		g_printerr ("\t-> %s\n", name);
 		g_free (name);
 		data += byte_length + 2;

Modified: trunk/plugins/excel/ms-excel-read.h
==============================================================================
--- trunk/plugins/excel/ms-excel-read.h	(original)
+++ trunk/plugins/excel/ms-excel-read.h	Thu Feb  7 23:27:12 2008
@@ -50,7 +50,7 @@
 typedef struct {
 	GnmCellPos key;
 	guint8 *data;
-	guint32 data_len;
+	guint32 data_len, array_data_len;
 	gboolean is_array;
 } XLSharedFormula;
 
@@ -135,10 +135,12 @@
 
 char *excel_get_chars (GnmXLImporter const *importer,
 		       guint8 const *ptr, size_t length,
-				  gboolean use_utf16);
-char *excel_get_text  (GnmXLImporter const *importer,
-		       guint8 const *ptr, guint32 length,
-		       guint32 *byte_length);
+		       gboolean use_utf16);
+char * excel_get_text (GnmXLImporter const *importer,
+		       guint8 const *pos, guint32 length,
+		       guint32 *byte_length, guint32 maxlen);
+char *excel_biff_text_1 (GnmXLImporter const *importer, const BiffQuery *q, guint32 ofs);
+char *excel_biff_text_2 (GnmXLImporter const *importer, const BiffQuery *q, guint32 ofs);
 
 GnmColor	*excel_palette_get (GnmXLImporter *importer, gint idx);
 ExcelFont const *excel_font_get    (GnmXLImporter const *importer, unsigned idx);

Modified: trunk/plugins/excel/ms-formula-read.c
==============================================================================
--- trunk/plugins/excel/ms-formula-read.c	(original)
+++ trunk/plugins/excel/ms-formula-read.c	Thu Feb  7 23:27:12 2008
@@ -843,6 +843,39 @@
 	"PTG_REF_ERR_3D", "PTG_AREA_ERR_3D", "PTG_3E",	"PTG_3F"
 };
 
+
+static gboolean
+check_formula_len (int left, int needed)
+{
+	if (needed > left) {
+		g_warning ("File is most likely corrupted.\n"
+			   "(Needed %d bytes for formula item, has only %d.)",
+			   needed, left);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+#define CHECK_FORMULA_LEN(len_)					\
+do {								\
+	ptg_length = (len_);					\
+	if (check_formula_len (len_left, ptg_length + 1)) {	\
+		goto length_error;				\
+	}							\
+} while (0)							\
+
+#define CHECK_FORMULA_ARRAY_LEN(len_)				\
+do {								\
+	int needed_ = len_;					\
+	int left_ = array_length - (array_data - array_data0);	\
+	if (check_formula_len (left_, needed_)) {		\
+                if (v)						\
+			value_release (v);			\
+		goto length_error;				\
+	}							\
+} while (0)
+
 /**
  * Parse that RP Excel formula, see S59E2B.HTM
  * Return a dynamicly allocated GnmExpr containing the formula, or NULL
@@ -851,7 +884,7 @@
 excel_parse_formula1 (MSContainer const *container,
 		      ExcelReadSheet const *esheet,
 		      int fn_col, int fn_row,
-		      guint8 const *mem, guint16 length,
+		      guint8 const *mem, guint16 length, guint16 array_length,
 		      gboolean shared,
 		      gboolean *array_element)
 {
@@ -861,7 +894,8 @@
 	guint8 const *cur = mem + 1;
 
 	/* Array sizes and values are stored at the end of the stream */
-	guint8 const *array_data = mem + length;
+	guint8 const *array_data0 = mem + length;
+	guint8 const *array_data = array_data0;
 
 	int len_left = length;
 	GnmExprList *stack = NULL;
@@ -901,8 +935,14 @@
 			XLSharedFormula *sf;
 			GnmCellPos top_left;
 
+			if (ver >= MS_BIFF_V3) {
+				CHECK_FORMULA_LEN(3);
+				top_left.col = GSF_LE_GET_GUINT16 (cur+2);
+			} else {
+				CHECK_FORMULA_LEN(4);
+				top_left.col = GSF_LE_GET_GUINT8 (cur+2);
+			}
 			top_left.row = GSF_LE_GET_GUINT16 (cur+0);
-			top_left.col = (ver >= MS_BIFF_V3) ? GSF_LE_GET_GUINT16 (cur+2) : GSF_LE_GET_GUINT8 (cur+2);
 			sf = excel_sheet_shared_formula (esheet, &top_left);
 
 			if (sf == NULL) {
@@ -926,7 +966,8 @@
 
 			d (0, fprintf (stderr, "Parse shared formula\n"););
 			expr = excel_parse_formula1 (container, esheet, fn_col, fn_row,
-				sf->data, sf->data_len, TRUE, array_element);
+						     sf->data, sf->data_len, sf->array_data_len,
+						     TRUE, array_element);
 
 			parse_list_push (&stack, expr);
 			ptg_length = length; /* Force it to be the only token */
@@ -937,8 +978,14 @@
 			XLDataTable *dt;
 			GnmCellPos top_left;
 
+			if (ver >= MS_BIFF_V3) {
+				CHECK_FORMULA_LEN(3);
+				top_left.col = GSF_LE_GET_GUINT16 (cur+2);
+			} else {
+				CHECK_FORMULA_LEN(4);
+				top_left.col = GSF_LE_GET_GUINT8 (cur+2);
+			}
 			top_left.row = GSF_LE_GET_GUINT16 (cur+0);
-			top_left.col = (ver >= MS_BIFF_V3) ? GSF_LE_GET_GUINT16 (cur+2) : GSF_LE_GET_GUINT8 (cur+2);
 			dt = excel_sheet_data_table (esheet, &top_left);
 
 			if (dt == NULL) {
@@ -1018,15 +1065,17 @@
 			break;
 
 		case FORMULA_PTG_ATTR : { /* FIXME: not fully implemented */
-			guint8  grbit = GSF_LE_GET_GUINT8 (cur);
+			guint8 grbit;
 			guint16 w;
 			if (ver >= MS_BIFF_V3) {
+				CHECK_FORMULA_LEN(3);
 				w = GSF_LE_GET_GUINT16 (cur+1);
-				ptg_length = 3;
 			} else {
+				CHECK_FORMULA_LEN(2);
 				w = GSF_LE_GET_GUINT8 (cur+1);
-				ptg_length = 2;
 			}
+
+			grbit = GSF_LE_GET_GUINT8 (cur);
 			if (grbit == 0x00) {
 #if 0
 				ms_excel_dump_cellname (container->importer, esheet, fn_col, fn_row);
@@ -1080,61 +1129,47 @@
 		break;
 
 		case FORMULA_PTG_SHEET:
+			CHECK_FORMULA_LEN(10);
 			g_warning ("PTG_SHEET! please send us a copy of this file.");
-			ptg_length = 10;
 			break;
 
 		case FORMULA_PTG_SHEET_END:
+			CHECK_FORMULA_LEN(4);
 			g_warning ("PTG_SHEET_END! please send us a copy of this file.");
-			ptg_length = 4;
 			break;
 
 		case FORMULA_PTG_ERR:
+			CHECK_FORMULA_LEN(1);
 			parse_list_push_raw (&stack, biff_get_error (NULL, GSF_LE_GET_GUINT8 (cur)));
-			ptg_length = 1;
 			break;
 
 		case FORMULA_PTG_INT:
+			CHECK_FORMULA_LEN(2);
 			parse_list_push_raw (&stack, value_new_int (GSF_LE_GET_GUINT16 (cur)));
-			ptg_length = 2;
 			break;
 
 		case FORMULA_PTG_BOOL:
+			CHECK_FORMULA_LEN(1);
 			parse_list_push_raw (&stack, value_new_bool (GSF_LE_GET_GUINT8 (cur)));
-			ptg_length = 1;
 			break;
 
 		case FORMULA_PTG_NUM:
+			CHECK_FORMULA_LEN(8);
 			parse_list_push_raw (&stack, value_new_float (gsf_le_get_double (cur)));
-			ptg_length = 8;
 			break;
 
 		case FORMULA_PTG_STR: {
 			char *str;
 			guint32 byte_len;
-			int char_len = GSF_LE_GET_GUINT8 (cur);
+			int char_len;
 
-			if (char_len <= len_left) {
-				str = excel_get_text (container->importer, cur+1, char_len, &byte_len);
-				ptg_length = 1 + byte_len;
-				/* data validation has a non-standard form of expression
-				 */
-#if 0
-				if (str != NULL && ) {
-					int res_char_len = g_utf8_strlen (str,  byte_len);
-				}
-#endif
-			} else {
-				str = NULL;
+			CHECK_FORMULA_LEN(1);
+			char_len = GSF_LE_GET_GUINT8 (cur);
 
-#if 0
-				/* we can not flag this because some versions of gnumeric
-				 * produced invalid output where "" was stored as
-				 * PTG_STR with no length **/
-				g_warning ("invalid string of len %d, larger than remaining space %d",
-					   len, len_left);
-#endif
-			}
+			str = excel_get_text (container->importer, cur+1,
+					      char_len, &byte_len,
+					      len_left - 1);
+			ptg_length = 1 + byte_len;
 
 			if (str != NULL) {
 				d (2, fprintf (stderr, "   -> '%s'\n", str););
@@ -1147,7 +1182,7 @@
 		}
 
 		case FORMULA_PTG_EXTENDED : { /* Extended Ptgs for Biff8 */
-			ptg_length = 1;
+			CHECK_FORMULA_LEN(1);
 			switch ((eptg = GSF_LE_GET_GUINT8 (cur))) {
 			default :
 				g_warning ("EXCEL : unknown ePtg type %02x", eptg);
@@ -1248,11 +1283,15 @@
 		break;
 
 		case FORMULA_PTG_ARRAY : {
-			unsigned cols = GSF_LE_GET_GUINT8  (array_data + 0);
-			unsigned rows = GSF_LE_GET_GUINT16 (array_data + 1);
-			unsigned lpx, lpy, elem_len = 0;
-			GnmValue *v, *elem;
-			guint8 val_type;
+			unsigned cols, rows;
+			unsigned lpx, lpy;
+			GnmValue *v = NULL;
+
+			CHECK_FORMULA_LEN(7);
+			CHECK_FORMULA_ARRAY_LEN(3);
+			cols = GSF_LE_GET_GUINT8  (array_data + 0);
+			rows = GSF_LE_GET_GUINT16 (array_data + 1);
+			array_data += 3;
 
 			if (ver >= MS_BIFF_V8) {
 				cols++;
@@ -1261,7 +1300,6 @@
 				cols = 256;
 
 			v = value_new_array (cols, rows);
-			ptg_length = 7;
 
 #ifndef NO_DEBUG_EXCEL
 			if (ms_excel_formula_debug > 4) {
@@ -1272,10 +1310,14 @@
 					cols, rows);
 			}
 #endif
-			array_data += 3;
 			for (lpy = 0; lpy < rows; lpy++) {
 				for (lpx = 0; lpx < cols; lpx++) {
+					GnmValue *elem;
+					guint8 val_type;
+
+					CHECK_FORMULA_ARRAY_LEN(1);
 					val_type = GSF_LE_GET_GUINT8 (array_data);
+					array_data++;
 #ifndef NO_DEBUG_EXCEL
 					if (ms_excel_formula_debug > 5) {
 						fprintf (stderr, "\tArray elem type 0x%x (%d,%d)\n", val_type, lpx, lpy);
@@ -1283,23 +1325,29 @@
 #endif
 					switch (val_type) {
 					case 1:
-						elem = value_new_float (gsf_le_get_double (array_data+1));
-						elem_len = 9;
+						CHECK_FORMULA_ARRAY_LEN(8);
+						elem = value_new_float (gsf_le_get_double (array_data));
+						array_data += 8;
 						break;
 
 					case 2: {
-						guint32 len;
+						guint32 len, chars;
 						char *str;
 
 						if (ver >= MS_BIFF_V8) {
-							str = excel_get_text (container->importer, array_data + 3,
-								GSF_LE_GET_GUINT16 (array_data+1), &len);
-							elem_len = len + 3;
+							CHECK_FORMULA_ARRAY_LEN(2);
+							chars = GSF_LE_GET_GUINT16 (array_data);
+							array_data += 2;
 						} else {
-							str = excel_get_text (container->importer, array_data + 2,
-								GSF_LE_GET_GUINT8 (array_data+1), &len);
-							elem_len = len + 2;
+							CHECK_FORMULA_ARRAY_LEN(1);
+							chars = GSF_LE_GET_GUINT8 (array_data);
+							array_data++;
 						}
+						str = excel_get_text
+							(container->importer, array_data,
+							 chars, &len,
+							 array_length - (array_data - array_data0));
+						array_data += len;
 
 						if (str) {
 #ifndef NO_DEBUG_EXCEL
@@ -1314,22 +1362,21 @@
 					}
 
 					case 4:
-						elem = value_new_bool (array_data [1] ? TRUE : FALSE);
-						elem_len = 9;
+						CHECK_FORMULA_ARRAY_LEN(8);
+						elem = value_new_bool (array_data[0] ? TRUE : FALSE);
 						break;
 					case 16:
-						elem = biff_get_error (NULL, array_data [1]);
-						elem_len = 9;
+						CHECK_FORMULA_ARRAY_LEN(8);
+						elem = biff_get_error (NULL, array_data[0]);
 						break;
 
 					default :
-						fprintf (stderr, "FIXME: Duff array item type %d @ %s%d:%d,%d with %d\n",
-							val_type, col_name(fn_col), fn_row+1, lpx, lpy, elem_len);
-						gsf_mem_dump (array_data-elem_len-9, 9+elem_len+9);
+						fprintf (stderr, "FIXME: Duff array item type %d @ %s%d:%d,%d\n",
+							val_type, col_name(fn_col), fn_row+1, lpx, lpy);
+						gsf_mem_dump (array_data-1, 9);
 						elem = value_new_empty ();
 					}
 					value_array_set (v, lpx, lpy, elem);
-					array_data += elem_len;
 				}
 			}
 			parse_list_push_raw (&stack, v);
@@ -1341,10 +1388,10 @@
 			int iftab;
 
 			if (ver >= MS_BIFF_V4) {
-				ptg_length = 2;
+				CHECK_FORMULA_LEN(2);
 				iftab = GSF_LE_GET_GUINT16 (cur);
 			} else {
-				ptg_length = 1;
+				CHECK_FORMULA_LEN(1);
 				iftab = GSF_LE_GET_GUINT8 (cur);
 			}
 
@@ -1356,7 +1403,7 @@
 		}
 
 		case FORMULA_PTG_FUNC_VAR: {
-			int const numargs = (GSF_LE_GET_GUINT8 ( cur ) & 0x7f);
+			int numargs;
 			/* index into fn table */
 			int iftab;
 #if 0
@@ -1366,12 +1413,13 @@
 			int const cmdquiv = (GSF_LE_GET_GUINT16 (cur+1) & 0x8000);
 #endif
 			if (ver >= MS_BIFF_V4) {
-				ptg_length = 3;
+				CHECK_FORMULA_LEN(3);
 				iftab = (GSF_LE_GET_GUINT16 (cur+1) & 0x7fff);
 			} else {
-				ptg_length = 2;
+				CHECK_FORMULA_LEN(2);
 				iftab = GSF_LE_GET_GUINT8 (cur+1);
 			}
+			numargs = (GSF_LE_GET_GUINT8 (cur) & 0x7f);
 
 			if (!make_function (&stack, iftab, numargs, container->importer->wb)) {
 				error = TRUE;
@@ -1381,17 +1429,18 @@
 		}
 
 		case FORMULA_PTG_NAME: {
-			guint16 name_idx = GSF_LE_GET_GUINT16 (cur);
+			guint16 name_idx;
 			GPtrArray    *names;
 			GnmExpr const*name;
 			GnmNamedExpr *nexpr = NULL;
 
 			if (ver >= MS_BIFF_V8)
-				ptg_length = 4;  /* Docs are wrong, no ixti */
+				CHECK_FORMULA_LEN(4);  /* Docs are wrong, no ixti */
 			else if (ver >= MS_BIFF_V5)
-				ptg_length = 14;
+				CHECK_FORMULA_LEN(14);
 			else
-				ptg_length = 10;
+				CHECK_FORMULA_LEN(10);
+			name_idx = GSF_LE_GET_GUINT16 (cur);
 
 			names = container->importer->names;
 			if (name_idx < 1 || names->len < name_idx ||
@@ -1426,29 +1475,29 @@
 		break;
 
 		case FORMULA_PTG_REF_ERR:
-			ptg_length = (ver >= MS_BIFF_V8) ? 4 : 3;
+			CHECK_FORMULA_LEN(ver >= MS_BIFF_V8 ? 4 : 3);
 			parse_list_push_raw (&stack, value_new_error_REF (NULL));
 			break;
 
 		case FORMULA_PTG_AREA_ERR:
-			ptg_length = (ver >= MS_BIFF_V8) ? 8 : 6;
+			CHECK_FORMULA_LEN(ver >= MS_BIFF_V8 ? 8 : 6);
 			parse_list_push_raw (&stack, value_new_error_REF (NULL));
 			break;
 
 		case FORMULA_PTG_REF: case FORMULA_PTG_REFN: {
 			GnmCellRef ref;
 			if (ver >= MS_BIFF_V8) {
+				CHECK_FORMULA_LEN(4);
 				getRefV8 (&ref,
 					  GSF_LE_GET_GUINT16 (cur),
 					  GSF_LE_GET_GUINT16 (cur + 2),
 					  fn_col, fn_row, ptgbase == FORMULA_PTG_REFN);
-				ptg_length = 4;
 			} else {
+				CHECK_FORMULA_LEN(3);
 				getRefV7 (&ref,
 					  GSF_LE_GET_GUINT8 (cur+2),
 					  GSF_LE_GET_GUINT16 (cur),
 					  fn_col, fn_row, ptgbase == FORMULA_PTG_REFN);
-				ptg_length = 3;
 			}
 			parse_list_push (&stack, gnm_expr_new_cellref (&ref));
 			break;
@@ -1457,6 +1506,7 @@
 		case FORMULA_PTG_AREA: case FORMULA_PTG_AREAN: {
 			GnmCellRef first, last;
 			if (ver >= MS_BIFF_V8) {
+				CHECK_FORMULA_LEN(8);
 				getRefV8 (&first,
 					  GSF_LE_GET_GUINT16 (cur+0),
 					  GSF_LE_GET_GUINT16 (cur+4),
@@ -1465,8 +1515,8 @@
 					  GSF_LE_GET_GUINT16 (cur+2),
 					  GSF_LE_GET_GUINT16 (cur+6),
 					  fn_col, fn_row, ptgbase == FORMULA_PTG_AREAN);
-				ptg_length = 8;
 			} else {
+				CHECK_FORMULA_LEN(6);
 				getRefV7 (&first,
 					  GSF_LE_GET_GUINT8 (cur+4),
 					  GSF_LE_GET_GUINT16 (cur+0),
@@ -1475,7 +1525,6 @@
 					  GSF_LE_GET_GUINT8 (cur+5),
 					  GSF_LE_GET_GUINT16 (cur+2),
 					  fn_col, fn_row, ptgbase == FORMULA_PTG_AREAN);
-				ptg_length = 6;
 			}
 
 			parse_list_push_raw (&stack, value_new_cellrange (&first, &last, fn_col, fn_row));
@@ -1485,12 +1534,12 @@
 		case FORMULA_PTG_MEM_AREA :
 		case FORMULA_PTG_MEM_ERR :
 			/* ignore this, we handle at run time */
-			ptg_length = 6;
+			CHECK_FORMULA_LEN(6);
 			break;
 
 		case FORMULA_PTG_MEM_FUNC:
 			/* ignore this, we handle at run time */
-			ptg_length = 2;
+			CHECK_FORMULA_LEN(2);
 			break;
 
 		case FORMULA_PTG_NAME_X : {
@@ -1501,9 +1550,13 @@
 			Sheet *sheet = NULL;
 
 			if (ver >= MS_BIFF_V8) {
-				guint16 sheet_idx = GSF_LE_GET_GINT16 (cur);
-				ExcelExternSheetV8 const *es = excel_externsheet_v8 (
-					container->importer, sheet_idx);
+				guint16 sheet_idx;
+				ExcelExternSheetV8 const *es;
+
+				CHECK_FORMULA_LEN(6);
+				sheet_idx = GSF_LE_GET_GINT16 (cur);
+				es = excel_externsheet_v8 (container->importer, sheet_idx);
+
 				if (es != NULL && es->supbook < container->importer->v8.supbook->len) {
 					ExcelSupBook const *sup = &g_array_index (
 						container->importer->v8.supbook,
@@ -1520,10 +1573,11 @@
 
 				d (2, fprintf (stderr, "name %hu : externsheet %hu\n",
 					       name_idx, sheet_idx););
-
-				ptg_length = 6;
 			} else {
-				gint16 sheet_idx = GSF_LE_GET_GINT16 (cur);
+				gint16 sheet_idx;
+
+				CHECK_FORMULA_LEN(24);
+				sheet_idx = GSF_LE_GET_GINT16 (cur);
 				name_idx  = GSF_LE_GET_GUINT16 (cur+10);
 #if 0
 				gsf_mem_dump (cur, 24);
@@ -1536,7 +1590,6 @@
 				} else
 					names = container->v7.externnames;
 				sheet = excel_externsheet_v7 (container, sheet_idx);
-				ptg_length = 24;
 			}
 
 			if (names == NULL || name_idx < 1 || names->len < name_idx ||
@@ -1563,19 +1616,19 @@
 		case FORMULA_PTG_REF_3D : { /* see S59E2B.HTM */
 			GnmCellRef first, last;
 			if (ver >= MS_BIFF_V8) {
+				CHECK_FORMULA_LEN(6);
 				getRefV8 (&first,
 					  GSF_LE_GET_GUINT16 (cur + 2),
 					  GSF_LE_GET_GUINT16 (cur + 4),
 					  fn_col, fn_row, 0);
 				last = first;
-				ptg_length = 6;
 			} else {
+				CHECK_FORMULA_LEN(17);
 				getRefV7 (&first,
 					  GSF_LE_GET_GUINT8  (cur + 16),
 					  GSF_LE_GET_GUINT16 (cur + 14),
 					  fn_col, fn_row, shared);
 				last = first;
-				ptg_length = 17;
 			}
 
 			if (excel_formula_parses_ref_sheets (container, cur, &first.sheet, &last.sheet))
@@ -1592,6 +1645,7 @@
 			GnmCellRef first, last;
 
 			if (ver >= MS_BIFF_V8) {
+				CHECK_FORMULA_LEN(10);
 				getRefV8 (&first,
 					  GSF_LE_GET_GUINT16 (cur+2),
 					  GSF_LE_GET_GUINT16 (cur+6),
@@ -1600,8 +1654,8 @@
 					  GSF_LE_GET_GUINT16 (cur+4),
 					  GSF_LE_GET_GUINT16 (cur+8),
 					  fn_col, fn_row, 0);
-				ptg_length = 10;
 			} else {
+				CHECK_FORMULA_LEN(20);
 				getRefV7 (&first,
 					  GSF_LE_GET_GUINT8 (cur+18),
 					  GSF_LE_GET_GUINT16 (cur+14),
@@ -1610,7 +1664,6 @@
 					  GSF_LE_GET_GUINT8 (cur+19),
 					  GSF_LE_GET_GUINT16 (cur+16),
 					  fn_col, fn_row, shared);
-				ptg_length = 20;
 			}
 			if (excel_formula_parses_ref_sheets (container, cur, &first.sheet, &last.sheet))
 				parse_list_push_raw (&stack, value_new_error_REF (NULL));
@@ -1620,12 +1673,12 @@
 		}
 
 		case FORMULA_PTG_REF_ERR_3D :
-			ptg_length = (ver >= MS_BIFF_V8) ? 6 : 17;
+			CHECK_FORMULA_LEN(ver >= MS_BIFF_V8 ? 6 : 17);
 			parse_list_push_raw (&stack, value_new_error_REF (NULL));
 			break;
 
 		case FORMULA_PTG_AREA_ERR_3D :
-			ptg_length = (ver >= MS_BIFF_V8) ? 10 : 20;
+			CHECK_FORMULA_LEN(ver >= MS_BIFF_V8 ? 10 : 20);
 			parse_list_push_raw (&stack, value_new_error_REF (NULL));
 			break;
 
@@ -1645,6 +1698,8 @@
 		len_left -= ptg_length + 1;
 	}
 
+ length_error:
+
 	if (error) {
 		g_printerr ("formula data : %s\n", (shared?" (shared)":"(NOT shared)"));
 		gsf_mem_dump (mem, length);
@@ -1676,19 +1731,21 @@
 #endif
 	return parse_list_pop (&stack);
 }
+#undef CHECK_FORMULA_LEN
+#undef CHECK_FORMULA_ARRAY_LEN
 
 GnmExprTop const *
 excel_parse_formula (MSContainer const *container,
 		     ExcelReadSheet const *esheet,
 		     int fn_col, int fn_row,
-		     guint8 const *mem, guint16 length,
+		     guint8 const *mem, guint16 length, guint16 array_length,
 		     gboolean shared,
 		     gboolean *array_element)
 {
 	GnmExprTop const *texpr =
 		gnm_expr_top_new (excel_parse_formula1 (container, esheet,
 							fn_col, fn_row,
-							mem, length,
+							mem, length, array_length,
 							shared,
 							array_element));
 	return texpr

Modified: trunk/plugins/excel/ms-formula-read.h
==============================================================================
--- trunk/plugins/excel/ms-formula-read.h	(original)
+++ trunk/plugins/excel/ms-formula-read.h	Thu Feb  7 23:27:12 2008
@@ -18,10 +18,10 @@
 
 GnmExprTop const *
 excel_parse_formula (MSContainer const *container,
-					 ExcelReadSheet const *esheet,
-					 int fn_col, int fn_row,
-					 guint8 const *mem, guint16 length,
-					 gboolean shared,
-					 gboolean *array_element);
+		     ExcelReadSheet const *esheet,
+		     int fn_col, int fn_row,
+		     guint8 const *mem, guint16 length, guint16 array_length,
+		     gboolean shared,
+		     gboolean *array_element);
 
 #endif /* GNM_MS_FORMULA_R_H */

Modified: trunk/plugins/excel/ms-obj.c
==============================================================================
--- trunk/plugins/excel/ms-obj.c	(original)
+++ trunk/plugins/excel/ms-obj.c	Thu Feb  7 23:27:12 2008
@@ -883,10 +883,11 @@
 	char *type;
 	guint32 len;
 
-	if ((data+16) > last)
+	if (last - data < 16)
 		return;
 	type = excel_get_text (c->importer, data + 16,
-		GSF_LE_GET_GUINT16 (data + 14 ), &len);
+			       GSF_LE_GET_GUINT16 (data + 14),
+			       &len, last - data);
 	if (NULL == type || strncmp (type, "Forms.", 6)) {
 		g_free (type);
 		return;

Modified: trunk/plugins/excel/ms-pivot.c
==============================================================================
--- trunk/plugins/excel/ms-pivot.c	(original)
+++ trunk/plugins/excel/ms-pivot.c	Thu Feb  7 23:27:12 2008
@@ -100,8 +100,7 @@
 		guint16 base_fields	= GSF_LE_GET_GUINT16 (q->data + 10);	/* base */
 		/* guint16 zero */
 		guint16 type		= GSF_LE_GET_GUINT16 (q->data + 16);
-		char *who		= excel_get_text (s->importer,
-			q->data + 20, GSF_LE_GET_GUINT16 (q->data + 18), NULL);
+		char *who		= excel_biff_text_2 (s->importer, q, 18);
 		fprintf (stderr, "num_rec = %u;\nstream_id = %hu;\n"
 			 "rec per block = %hu;\nbase fields = %hu;\ntotal fields = %hu;\n"
 			 "last modified by = '%s';type = 0x%x, flags = 0x%x;\n",
@@ -139,8 +138,7 @@
 			guint16 grouped_items	= GSF_LE_GET_GUINT16  (q->data + 8);
 			guint16 base_items	= GSF_LE_GET_GUINT16  (q->data + 10);
 			guint16 std_items	= GSF_LE_GET_GUINT16  (q->data + 12);
-			char *name = excel_get_text (s->importer, q->data + 16,
-				GSF_LE_GET_GUINT16 (q->data + 14), NULL);
+			char *name = excel_biff_text_2 (s->importer, q, 14);
 			switch (index_type) {
 			case 1 : /* items follow field description with no index */
 				s->num_items  = GSF_LE_GET_GUINT16  (q->data + 6);
@@ -212,8 +210,7 @@
 		break;
 
 		case BIFF_SXSTRING: if (check_min_len (q, 2)) {
-			char *val = excel_get_text (s->importer, q->data + 2,
-				GSF_LE_GET_GUINT16 (q->data + 0), NULL);
+			char *val = excel_biff_text_2 (s->importer, q, 0);
 			d_item (s);
 			d (2, fprintf (stderr, "'%s' (string);\n", val););
 			g_free (val);



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