Am Dienstag, 4. Oktober 2005 19:15 schrieb Jean-Marc Lasgouttes:
> >>>>> "Georg" == Georg Baum <[EMAIL PROTECTED]> writes:

> Georg> AFAICS Andre' is right and MathMacroInset is the only
> Georg> MathNestInset with 0 cells, so we could put the checks in
> Georg> MathMacroInset. We would then avoid the checks when they are
> Georg> not necessary. Would you prefer that?
> 
> Yes, if that makes the code intent be clearer. In this case, we should
> probably assert on bad values in MathNestInset.

It looks like the attached, then. The asserts (if we add any) belong in 
MathNestInset::cell, MathGridInset::col and MathGridInset::row, because 
bad indices would harm there.
I am not sure if we really need the asserts: MathMacroInset is really 
special. Apart from that I believe that the cell/column/row handling code 
is very robust in general. The asserts are now in a central place that 
gets called a lot. Shall I commit with or without the asserts?


Georg
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/ChangeLog lyx-1.4-cvs/src/mathed/ChangeLog
--- lyx-1.4-clean/src/mathed/ChangeLog	2005-10-03 14:27:24.000000000 +0200
+++ lyx-1.4-cvs/src/mathed/ChangeLog	2005-10-04 21:00:01.000000000 +0200
@@ -1,3 +1,13 @@
+2005-10-04  Georg Baum  <[EMAIL PROTECTED]>
+
+	* math_macro.C (editXY): new, fix crash (bug 2060)
+	* math_macro.C (cursorPos): new, fix potential crash
+	* math_macro.C (drawSelection): new, fix potential crash
+	* math_gridinset.C (col, row): assert on valid index
+	* math_nestinset.C (cell, drawSelection, editXY): ditto
+	* math_nestinset.C (doDispatch): fix crash when inserting math macros
+	with 0 arguments
+
 2005-09-30  Jean-Marc Lasgouttes  <[EMAIL PROTECTED]>
 
 	* math_nestinset.C (doDispatch): do not leave the inset after
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_gridinset.C lyx-1.4-cvs/src/mathed/math_gridinset.C
--- lyx-1.4-clean/src/mathed/math_gridinset.C	2005-07-18 21:19:33.000000000 +0200
+++ lyx-1.4-cvs/src/mathed/math_gridinset.C	2005-10-04 20:45:50.000000000 +0200
@@ -308,12 +347,14 @@ MathGridInset::row_type MathGridInset::n
 
 MathGridInset::col_type MathGridInset::col(idx_type idx) const
 {
+	BOOST_ASSERT(nargs() > idx);
 	return idx % ncols();
 }
 
 
 MathGridInset::row_type MathGridInset::row(idx_type idx) const
 {
+	BOOST_ASSERT(nargs() > idx);
 	return idx / ncols();
 }
 
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_macro.C lyx-1.4-cvs/src/mathed/math_macro.C
--- lyx-1.4-clean/src/mathed/math_macro.C	2005-07-17 14:58:03.000000000 +0200
+++ lyx-1.4-cvs/src/mathed/math_macro.C	2005-10-04 20:57:38.000000000 +0200
@@ -46,6 +46,15 @@ string MathMacro::name() const
 }
 
 
+void MathMacro::cursorPos(CursorSlice const & sl, bool boundary, int & x,
+		int & y) const
+{
+	// We may have 0 arguments, but MathNestInset requires at least one.
+	if (nargs() > 0)
+		MathNestInset::cursorPos(sl, boundary, x, y);
+}
+
+
 void MathMacro::metrics(MetricsInfo & mi, Dimension & dim) const
 {
 	if (!MacroTable::globalMacros().has(name())) {
@@ -102,10 +111,27 @@ void MathMacro::draw(PainterInfo & pi, i
 }
 
 
+void MathMacro::drawSelection(PainterInfo & pi, int x, int y) const
+{
+	// We may have 0 arguments, but MathNestInset requires at least one.
+	if (nargs() > 0)
+		MathNestInset::drawSelection(pi, x, y);
+}
+
+
 void MathMacro::validate(LaTeXFeatures & features) const
 {
 	if (name() == "binom" || name() == "mathcircumflex")
 		features.require(name());
+}
+
+
+InsetBase * MathMacro::editXY(LCursor & cur, int x, int y)
+{
+	// We may have 0 arguments, but MathNestInset requires at least one.
+	if (nargs() > 0)
+		return MathNestInset::editXY(cur, x, y);
+	return this;
 }
 
 
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_macro.h lyx-1.4-cvs/src/mathed/math_macro.h
--- lyx-1.4-clean/src/mathed/math_macro.h	2004-11-24 17:46:19.000000000 +0100
+++ lyx-1.4-cvs/src/mathed/math_macro.h	2005-10-04 20:38:48.000000000 +0200
@@ -28,8 +28,14 @@ public:
 	void draw(PainterInfo & pi, int x, int y) const;
 	///
 	void drawExpanded(PainterInfo & pi, int x, int y) const;
+	/// draw selection background
+	void drawSelection(PainterInfo & pi, int x, int y) const;
 	///
 	void metrics(MetricsInfo & mi, Dimension & dim) const;
+	/// get cursor position
+	void cursorPos(CursorSlice const & sl, bool boundary, int & x, int & y) const;
+	///
+	InsetBase * editXY(LCursor & cur, int x, int y);
 	///
 	std::string name() const;
 	///
@@ -60,7 +66,7 @@ private:
 	std::string name_;
 	/// the unexpanded macro defintition
 	mutable MathArray tmpl_;
-	/// the matcro substituted with our args
+	/// the macro substituted with our args
 	mutable MathArray expanded_;
 };
 
diff -p -r -U 3 -X excl.tmp lyx-1.4-clean/src/mathed/math_nestinset.C lyx-1.4-cvs/src/mathed/math_nestinset.C
--- lyx-1.4-clean/src/mathed/math_nestinset.C	2005-10-03 14:27:29.000000000 +0200
+++ lyx-1.4-cvs/src/mathed/math_nestinset.C	2005-10-04 20:42:18.000000000 +0200
@@ -78,12 +78,14 @@ MathInset::idx_type MathNestInset::nargs
 
 MathArray & MathNestInset::cell(idx_type i)
 {
+	BOOST_ASSERT(i < cells_.size());
 	return cells_[i];
 }
 
 
 MathArray const & MathNestInset::cell(idx_type i) const
 {
+	BOOST_ASSERT(i < cells_.size());
 	return cells_[i];
 }
 
@@ -219,6 +221,7 @@ void MathNestInset::draw(PainterInfo & p
 
 void MathNestInset::drawSelection(PainterInfo & pi, int x, int y) const
 {
+	BOOST_ASSERT(nargs() > 0);
 	// FIXME: hack to get position cache warm
 	draw(pi, x, y);
 
@@ -859,7 +867,10 @@ void MathNestInset::doDispatch(LCursor &
 		int cell(0);
 		if (cmd.argument == "\\root")
 			cell = 1;
-		if (ar.size() == 1 && (ar[0].nucleus()->asNestInset())) {
+		// math macros are nest insets and may have 0 cells.
+		// handleNest would crash in this case.
+		if (ar.size() == 1 && (ar[0].nucleus()->asNestInset()) &&
+		    ar[0].nucleus()->nargs() > cell) {
 			cur.handleNest(ar[0], cell);
 		} else
 			cur.niceInsert(cmd.argument);
@@ -1000,9 +1003,11 @@ void MathNestInset::edit(LCursor & cur, 
 
 InsetBase * MathNestInset::editXY(LCursor & cur, int x, int y)
 {
+	idx_type const n = nargs();
+	BOOST_ASSERT(n > 0);
 	int idx_min = 0;
 	int dist_min = 1000000;
-	for (idx_type i = 0, n = nargs(); i != n; ++i) {
+	for (idx_type i = 0; i != n; ++i) {
 		int const d = cell(i).dist(x, y);
 		if (d < dist_min) {
 			dist_min = d;

Reply via email to