From 97cf2b6aef1e0d7bc88e863b5d1d9e2920be0dd2 Mon Sep 17 00:00:00 2001 From: Jean-Marc Lasgouttes Date: Tue, 27 Feb 2024 18:09:42 +0100 Subject: [PATCH] Avoid crash when inserting macro template in tabular inset The issue here is that macro templates are forbidden in InsetTabular (why? I do not know) and Text::getStatus does not enforce that properly. Text::insertInset is called and does nothing (because insertion is forbidden) and yet the cursor is changed to point into this non existent inset. Solution: 1/ block insertion of macro templates when not allowed 2/ (additional safety) when insertion of a math macro inset failed, do not try to set cursor inside the non-existing inset. Additionally clarify comments. --- src/Text.cpp | 27 +++++++++++++++------------ src/Text.h | 7 ++++--- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/Text.cpp b/src/Text.cpp index 8c8c0bf40a..9fb59b5ec9 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -2965,12 +2965,12 @@ void Text::setParagraphs(Cursor const & cur, ParagraphParameters const & p) } -// this really should just insert the inset and not move the cursor. -void Text::insertInset(Cursor & cur, Inset * inset) +// just insert the inset and not move the cursor. +bool Text::insertInset(Cursor & cur, Inset * inset) { LBUFERR(this == cur.text()); LBUFERR(inset); - cur.paragraph().insertInset(cur.pos(), inset, cur.current_font, + return cur.paragraph().insertInset(cur.pos(), inset, cur.current_font, Change(cur.buffer()->params().track_changes ? Change::INSERTED : Change::UNCHANGED)); } @@ -5792,14 +5792,14 @@ void Text::dispatch(Cursor & cur, FuncRequest & cmd) InsetMathMacroTemplate * inset = new InsetMathMacroTemplate(cur.buffer(), from_utf8(token(s, ' ', 0)), nargs, false, type); inset->setBuffer(bv->buffer()); - insertInset(cur, inset); - - // enter macro inset and select the name - cur.push(*inset); - cur.top().pos() = cur.top().lastpos(); - cur.resetAnchor(); - cur.selection(true); - cur.top().pos() = 0; + if (insertInset(cur, inset)) { + // If insertion is successful, enter macro inset and select the name + cur.push(*inset); + cur.top().pos() = cur.top().lastpos(); + cur.resetAnchor(); + cur.selection(true); + cur.top().pos() = 0; + } } break; @@ -6734,12 +6734,15 @@ bool Text::getStatus(Cursor & cur, FuncRequest const & cmd, case LFUN_MATH_BIGDELIM: case LFUN_MATH_DISPLAY: case LFUN_MATH_MODE: - case LFUN_MATH_MACRO: case LFUN_MATH_SUBSCRIPT: case LFUN_MATH_SUPERSCRIPT: code = MATH_HULL_CODE; break; + case LFUN_MATH_MACRO: + code = MATHMACRO_CODE; + break; + case LFUN_REGEXP_MODE: code = MATH_HULL_CODE; enable = cur.buffer()->isInternal() && !cur.inRegexped(); diff --git a/src/Text.h b/src/Text.h index 45fb69c5be..8dc066a161 100644 --- a/src/Text.h +++ b/src/Text.h @@ -141,12 +141,13 @@ public: void forOutliner(docstring & os, size_t maxlen, pit_type start, pit_type end, bool shorten = true) const; - /// insert a character at cursor position + /// FIXME: investigate why those two function behave differently wrt cursor. + /// insert a character at cursor position and move cursor forward /// FIXME: replace Cursor with DocIterator. void insertChar(Cursor & cur, char_type c); - /// insert an inset at cursor position + /// insert an inset at cursor position; do not move cursor /// FIXME: replace Cursor with DocIterator. - void insertInset(Cursor & cur, Inset * inset); + bool insertInset(Cursor & cur, Inset * inset); /// try to handle that request /// FIXME: replace Cursor with DocIterator. -- 2.39.5