Merge pull request #2802 from shun-iwasawa/g/fix_macro_curvefx_crash

Fix Crash When Loading MacroFx Containing CurveFx
This commit is contained in:
Rodney 2019-10-14 04:13:37 -05:00 committed by GitHub
commit 310c4f0dfb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 23 deletions

View file

@ -703,11 +703,18 @@ void TFx::setNewIdentifier() { m_imp->m_id = ++m_imp->m_nextId; }
void TFx::loadData(TIStream &is) { void TFx::loadData(TIStream &is) {
std::string tagName; std::string tagName;
VersionNumber tnzVersion = is.getVersion(); VersionNumber tnzVersion = is.getVersion();
// Prevent to load "params" tag under "super" tag on saving macro fx.
// For now "params" tag is no longer saved under "super" tag.
// This is for keeping compatibility with older versions.
bool isInSuperTag = (is.getCurrentTagName() == "super");
QList<int> groupIds; QList<int> groupIds;
QList<std::wstring> groupNames; QList<std::wstring> groupNames;
while (is.openChild(tagName)) { while (is.openChild(tagName)) {
if (tagName == "params") { if (tagName == "params") {
if (isInSuperTag) { // skip loading "params" tag under "super" tag
is.skipCurrentTag();
continue;
}
while (!is.eos()) { while (!is.eos()) {
std::string paramName; std::string paramName;
while (is.openChild(paramName)) { while (is.openChild(paramName)) {
@ -829,29 +836,36 @@ void TFx::loadData(TIStream &is) {
//-------------------------------------------------- //--------------------------------------------------
void TFx::saveData(TOStream &os) { void TFx::saveData(TOStream &os) {
// Prevent to save "params" tag under "super" tag on saving macro fx.
// Parameters for macro fx are saved in "nodes" tag and corrected upon
// loading. Therefore, "params" tag is not needed and even causes crash if
// macrofx contains CurveFx (See the issue #2424)
bool isInSuperTag = (os.getCurrentTagName() == "super");
TFx *linkedSetRoot = this; TFx *linkedSetRoot = this;
if (m_imp->m_next != m_imp) { if (m_imp->m_next != m_imp) {
TFxImp *imp = m_imp->m_next; TFxImp *imp = m_imp->m_next;
int guard = 0; int guard = 0;
while (guard++ < 1000 && imp != m_imp) { while (guard++ < 1000 && imp != m_imp) {
if (imp->m_fx < linkedSetRoot) linkedSetRoot = imp->m_fx; if (imp->m_fx < linkedSetRoot) linkedSetRoot = imp->m_fx;
imp = imp->m_next; imp = imp->m_next;
} }
assert(imp == m_imp); assert(imp == m_imp);
assert(linkedSetRoot); assert(linkedSetRoot);
} }
if (linkedSetRoot == this) { if (linkedSetRoot == this) {
os.openChild("params"); if (!isInSuperTag) { // skip saving "params" tag under "super" tag
for (int i = 0; i < getParams()->getParamCount(); i++) { os.openChild("params");
std::string paramName = getParams()->getParamName(i); for (int i = 0; i < getParams()->getParamCount(); i++) {
const TParamVar *paramVar = getParams()->getParamVar(i); std::string paramName = getParams()->getParamName(i);
// skip saving for the obsolete parameters const TParamVar *paramVar = getParams()->getParamVar(i);
if (paramVar->isObsolete()) continue; // skip saving for the obsolete parameters
os.openChild(paramName); if (paramVar->isObsolete()) continue;
paramVar->getParam()->saveData(os); os.openChild(paramName);
paramVar->getParam()->saveData(os);
os.closeChild();
}
os.closeChild(); os.closeChild();
} }
os.closeChild();
} else { } else {
os.openChild("paramsLinkedTo"); os.openChild("paramsLinkedTo");
os << linkedSetRoot; os << linkedSetRoot;

View file

@ -24,7 +24,8 @@ namespace {
string escape(string v) { string escape(string v) {
int i = 0; int i = 0;
for (;;) { for (;;) {
// Removing escaping of apostrophe from Windows and OSX as it's not needed and causes problems // Removing escaping of apostrophe from Windows and OSX as it's not needed and
// causes problems
#ifdef LINUX #ifdef LINUX
i = v.find_first_of("\\\'\"", i); i = v.find_first_of("\\\'\"", i);
#else #else
@ -353,10 +354,11 @@ TOStream &TOStream::operator<<(string v) {
} }
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if ((!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') if ((!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') ||
|| v[i] < 32 // Less than ASCII for SPACE v[i] < 32 // Less than ASCII for SPACE
|| v[i] > 126 // Greater than ASCII for ~ || v[i] > 126 // Greater than ASCII for ~
) break; )
break;
if (i == len) if (i == len)
os << v << " "; os << v << " ";
else { else {
@ -381,10 +383,11 @@ TOStream &TOStream::operator<<(QString _v) {
} }
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
if ((!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') if ((!iswalnum(v[i]) && v[i] != '_' && v[i] != '%') ||
|| v[i] < 32 // Less than ASCII for SPACE v[i] < 32 // Less than ASCII for SPACE
|| v[i] > 126 // Greater than ASCII for ~ || v[i] > 126 // Greater than ASCII for ~
) break; )
break;
if (i == len) if (i == len)
os << v << " "; os << v << " ";
else { else {
@ -467,7 +470,7 @@ TOStream &TOStream::operator<<(const TPixel64 &v) {
void TOStream::cr() { void TOStream::cr() {
*(m_imp->m_os) << endl; *(m_imp->m_os) << endl;
for (int i = 0; i < m_imp->m_tab; i++) *(m_imp->m_os) << " "; for (int i = 0; i < m_imp->m_tab; i++) *(m_imp->m_os) << " ";
m_imp->m_justStarted = false; m_imp->m_justStarted = false;
} }
@ -584,6 +587,10 @@ bool TOStream::checkStatus() const {
return m_imp->m_os->rdstate() == ios_base::goodbit; return m_imp->m_os->rdstate() == ios_base::goodbit;
} }
std::string TOStream::getCurrentTagName() {
return (m_imp->m_tagStack.empty()) ? "" : m_imp->m_tagStack.back();
}
//=============================================================== //===============================================================
/*! /*!
This class contains TIStream's attributes. This class contains TIStream's attributes.
@ -1109,8 +1116,8 @@ TIStream &TIStream::operator>>(TPersist *&v) {
m_imp->m_currentTag = StreamTag(); m_imp->m_currentTag = StreamTag();
string tagName = tag.m_name; string tagName = tag.m_name;
std::map<std::string, string>::iterator it; std::map<std::string, string>::iterator it;
int id = -1; int id = -1;
it = tag.m_attributes.find("id"); it = tag.m_attributes.find("id");
if (it != tag.m_attributes.end()) id = atoi(it->second.c_str()); if (it != tag.m_attributes.end()) id = atoi(it->second.c_str());
// cout << "tagname = " << tagName << " id = " << id << endl; // cout << "tagname = " << tagName << " id = " << id << endl;
@ -1268,3 +1275,7 @@ void TIStream::setVersion(const VersionNumber &version) {
//--------------------------------------------------------------- //---------------------------------------------------------------
void TIStream::skipCurrentTag() { m_imp->skipCurrentTag(); } void TIStream::skipCurrentTag() { m_imp->skipCurrentTag(); }
//---------------------------------------------------------------
std::string TIStream::getCurrentTagName() { return m_imp->m_tagStack.back(); }

View file

@ -155,6 +155,8 @@ reimplementation of the TPersist::loadData() function.
void skipCurrentTag(); //!< Silently ignores the content of currently opened void skipCurrentTag(); //!< Silently ignores the content of currently opened
//! tag up to its end. //! tag up to its end.
std::string getCurrentTagName();
private: private:
// Not copyable // Not copyable
TIStream(const TIStream &); //!< Not implemented TIStream(const TIStream &); //!< Not implemented
@ -266,6 +268,8 @@ checking the status.
*/ */
bool checkStatus() const; //!< \b Flushes the stream and checks its validity. bool checkStatus() const; //!< \b Flushes the stream and checks its validity.
std::string getCurrentTagName();
private: private:
// Not copyable // Not copyable
TOStream(const TOStream &) = delete; //!< Not implemented TOStream(const TOStream &) = delete; //!< Not implemented