From bc79c9a27b7c752d3fe82939ae29b88950337e61 Mon Sep 17 00:00:00 2001 From: Enrico Forestieri Date: Mon, 5 Oct 2015 22:43:20 +0200 Subject: [PATCH] Fix #9490: SIGSEGV involving LyX macros --- A reproducible MWE (part II) --- src/mathed/MathMacro.cpp | 40 ++++++++++++++++++++++++++++++++++++---- src/mathed/MathMacro.h | 3 +++ status.21x | 2 ++ 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/mathed/MathMacro.cpp b/src/mathed/MathMacro.cpp index bc942be2d3..43892f6ab0 100644 --- a/src/mathed/MathMacro.cpp +++ b/src/mathed/MathMacro.cpp @@ -63,6 +63,8 @@ public: /// void setOwner(MathMacro * mathMacro) { mathMacro_ = mathMacro; } /// + MathMacro * owner() { return mathMacro_; } + /// InsetCode lyxCode() const { return ARGUMENT_PROXY_CODE; } /// void metrics(MetricsInfo & mi, Dimension & dim) const { @@ -138,6 +140,7 @@ MathMacro::MathMacro(Buffer * buf, docstring const & name) MathMacro::MathMacro(MathMacro const & that) : InsetMathNest(that), expanded_(that.buffer_) { + setBuffer(*that.buffer_); assign(that); } @@ -175,16 +178,45 @@ void MathMacro::assign(MathMacro const & that) ArgumentProxy * p = dynamic_cast(expanded_.cell(0)[i].nucleus()); if (p) p->setOwner(this); + + InsetMathNest * ni = expanded_.cell(0)[i].nucleus()->asNestInset(); + if (ni) + updateNestedChildren(this, ni); } - if (macro_ && lyxrc.preview == LyXRC::PREVIEW_ON) { - // As MathData::metrics() is not called when instant preview is - // on, we have to update macro_ by ourselves. In this case, we - // simply let it point to the last known good copy of MacroData. + if (macro_) { + // The macro_ pointer is updated when MathData::metrics() is + // called. However, when instant preview is on or the macro is + // not on screen, MathData::metrics() is not called and we may + // have a dangling pointer. As a safety measure, when a macro + // is copied, always let macro_ point to the backup copy of the + // MacroData structure. This backup is updated every time the + // macro is changed, so it will not become stale. macro_ = ¯oBackup_; } } +void MathMacro::updateNestedChildren(MathMacro * owner, InsetMathNest * ni) +{ + for (size_t i = 0; i < ni->nargs(); ++i) { + MathData & ar = ni->cell(i); + for (size_t j = 0; j < ar.size(); ++j) { + ArgumentProxy * ap = dynamic_cast + (ar[j].nucleus()); + if (ap) { + MathMacro * mm = ap->owner(); + if (mm->macro_) + mm->macro_ = &mm->macroBackup_; + ap->setOwner(owner); + } + InsetMathNest * imn = ar[j].nucleus()->asNestInset(); + if (imn) + updateNestedChildren(owner, imn); + } + } +} + + Inset * MathMacro::clone() const { MathMacro * copy = new MathMacro(*this); diff --git a/src/mathed/MathMacro.h b/src/mathed/MathMacro.h index 239495ef5a..c7c155c6d2 100644 --- a/src/mathed/MathMacro.h +++ b/src/mathed/MathMacro.h @@ -162,6 +162,9 @@ private: bool editMode(BufferView const * bv) const; /// Copy all members (except base class members) void assign(MathMacro const &); + /// Recursively update the pointers of all expanded macros + /// appearing in the arguments of the current macro + void updateNestedChildren(MathMacro *, InsetMathNest *); /// name of macro docstring name_; diff --git a/status.21x b/status.21x index 6f343fcbf0..e5038f751f 100644 --- a/status.21x +++ b/status.21x @@ -70,6 +70,8 @@ What's new * USER INTERFACE +- Fix crash when unfolding/copying macros containing other macros (bug 9490). + - Fix automatic insertion of longtable captions (bug 9692). - Fix setting of nested minipage via the dialog (bug 8716).