From f3a9773849a17eaffbab9e325ba5aa7e27b29dc1 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 25 Nov 2017 02:30:18 -0800 Subject: [PATCH] [muparser] Make some error handling in ParserBase explicit Return ParserError instead of throwing exceptions --- muparser-2.2.5/src/muParserBase.cpp | 1 - muparser-2.2.5/src/muParserDLL.cpp | 17 ++++--- muparser-2.2.5/src/muParserTest.cpp | 26 +++++----- muparser-2.2.5/src/muParserTokenReader.cpp | 55 +++++++++++++--------- 4 files changed, 58 insertions(+), 41 deletions(-) diff --git a/muparser-2.2.5/src/muParserBase.cpp b/muparser-2.2.5/src/muParserBase.cpp index a617b0544..3144a6eb2 100644 --- a/muparser-2.2.5/src/muParserBase.cpp +++ b/muparser-2.2.5/src/muParserBase.cpp @@ -1079,7 +1079,6 @@ OptionalError ParserBase::CreateRPN() const { case cmARG_SEP: if (stArgCount.empty()) return Error(ecUNEXPECTED_ARG_SEP, m_pTokenReader->GetPos()); - ++stArgCount.top(); // fallthrough intentional (no break!) diff --git a/muparser-2.2.5/src/muParserDLL.cpp b/muparser-2.2.5/src/muParserDLL.cpp index 6fca652a3..59d8e286a 100644 --- a/muparser-2.2.5/src/muParserDLL.cpp +++ b/muparser-2.2.5/src/muParserDLL.cpp @@ -42,6 +42,10 @@ #include "muParserDLL.h" #include "muParserInt.h" +static void throwIfError(mu::OptionalError oerr) { + if (oerr.has_error()) throw oerr.error(); +} + #define MU_TRY try { #define MU_CATCH \ } \ @@ -205,7 +209,7 @@ API_EXPORT(muFloat_t) mupEval(muParserHandle_t a_hParser) { API_EXPORT(void) mupSetExpr(muParserHandle_t a_hParser, const muChar_t* a_szExpr) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->SetExpr(a_szExpr); + throwIfError(p->SetExpr(a_szExpr)); MU_CATCH } @@ -411,7 +415,8 @@ mupDefineOprt(muParserHandle_t a_hParser, const muChar_t* a_szName, muFun2_t a_p muInt_t a_nPrec, muInt_t a_nOprtAsct, muBool_t a_bAllowOpt) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, a_bAllowOpt != 0); + throwIfError(p->DefineOprt(a_szName, a_pFun, a_nPrec, (mu::EOprtAssociativity)a_nOprtAsct, + a_bAllowOpt != 0)); MU_CATCH } @@ -420,7 +425,7 @@ API_EXPORT(void) mupDefineVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); + throwIfError(p->DefineVar(a_szName, a_pVar)); MU_CATCH } @@ -429,7 +434,7 @@ API_EXPORT(void) mupDefineBulkVar(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t* a_pVar) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineVar(a_szName, a_pVar); + throwIfError(p->DefineVar(a_szName, a_pVar)); MU_CATCH } @@ -438,7 +443,7 @@ API_EXPORT(void) mupDefineConst(muParserHandle_t a_hParser, const muChar_t* a_szName, muFloat_t a_fVal) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineConst(a_szName, a_fVal); + throwIfError(p->DefineConst(a_szName, a_fVal)); MU_CATCH } @@ -447,7 +452,7 @@ API_EXPORT(void) mupDefineStrConst(muParserHandle_t a_hParser, const muChar_t* a_szName, const muChar_t* a_szVal) { MU_TRY muParser_t* const p(AsParser(a_hParser)); - p->DefineStrConst(a_szName, a_szVal); + throwIfError(p->DefineStrConst(a_szName, a_szVal)); MU_CATCH } diff --git a/muparser-2.2.5/src/muParserTest.cpp b/muparser-2.2.5/src/muParserTest.cpp index 3266a2cdd..ac0b2ce83 100644 --- a/muparser-2.2.5/src/muParserTest.cpp +++ b/muparser-2.2.5/src/muParserTest.cpp @@ -41,6 +41,12 @@ using namespace std; namespace mu { namespace Test { + +static value_type getOrThrow(mu::ValueOrError voerr) { + if (voerr.has_error()) throw voerr.error(); + return *voerr; +} + int ParserTester::c_iCount = 0; //--------------------------------------------------------------------------------------------- @@ -93,14 +99,14 @@ int ParserTester::TestInterface() { p.DefineVar(_T("b"), &afVal[1]); p.DefineVar(_T("c"), &afVal[2]); p.SetExpr(_T("a+b+c")); - (void)p.Eval(); + getOrThrow(p.Eval()); } catch (...) { iStat += 1; // this is not supposed to happen } try { p.RemoveVar(_T("c")); - (void)p.Eval(); + getOrThrow(p.Eval()); iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted... } catch (...) { // failure is expected... @@ -323,12 +329,10 @@ int ParserTester::TestNames() { PARSER_THROWCHECK(Var, true, _T("a_min"), &a) PARSER_THROWCHECK(Var, true, _T("a_min0"), &a) PARSER_THROWCHECK(Var, true, _T("a_min9"), &a) - PARSER_THROWCHECK(Var, false, _T("a_min9"), 0) // Postfix operators // fail PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1) PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1) - PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0) // pass PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1) PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1) @@ -977,7 +981,7 @@ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail) p.DefineFun(_T("strfun2"), StrFun2); p.DefineFun(_T("strfun3"), StrFun3); p.SetExpr(a_str); - (void)p.Eval(); + getOrThrow(p.Eval()); } catch (ParserError &e) { // output the formula in case of an failed test if (a_bFail == false || (a_bFail == true && a_iErrc != e.GetCode())) { @@ -1021,10 +1025,10 @@ int ParserTester::EqnTestWithVarChange(const string_type &a_str, double a_fVar1, p.SetExpr(a_str); var = a_fVar1; - fVal[0] = *p.Eval(); + fVal[0] = getOrThrow(p.Eval()); var = a_fVar2; - fVal[1] = *p.Eval(); + fVal[1] = getOrThrow(p.Eval()); if (fabs(a_fRes1 - fVal[0]) > 0.0000000001) throw std::runtime_error("incorrect result (first pass)"); @@ -1136,8 +1140,8 @@ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass) // Test bytecode integrity // String parsing and bytecode parsing must yield the same result - fVal[0] = *p1->Eval(); // result from stringparsing - fVal[1] = *p1->Eval(); // result from bytecode + fVal[0] = getOrThrow(p1->Eval()); // result from stringparsing + fVal[1] = getOrThrow(p1->Eval()); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode / string parsing mismatch.")); @@ -1204,8 +1208,8 @@ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPa p.DefineVar(_T("c"), &vVarVal[2]); p.SetExpr(a_str); - fVal[0] = *p.Eval(); // result from stringparsing - fVal[1] = *p.Eval(); // result from bytecode + fVal[0] = getOrThrow(p.Eval()); // result from stringparsing + fVal[1] = getOrThrow(p.Eval()); // result from bytecode if (fVal[0] != fVal[1]) throw Parser::exception_type(_T("Bytecode corrupt.")); diff --git a/muparser-2.2.5/src/muParserTokenReader.cpp b/muparser-2.2.5/src/muParserTokenReader.cpp index 67a1b0b37..2dff4aed2 100644 --- a/muparser-2.2.5/src/muParserTokenReader.cpp +++ b/muparser-2.2.5/src/muParserTokenReader.cpp @@ -166,10 +166,13 @@ ParserTokenReader::token_type ParserTokenReader::ReadNextToken() { // string_type strTok; int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos); - if (iEnd != m_iPos) Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + if (iEnd != m_iPos) { + Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok); + return {}; + } Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos)); - return token_type(); + return {}; } //--------------------------------------------------------------------------- @@ -267,7 +270,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { // The assignment operator need special treatment if (i == cmASSIGN && m_iSynFlags & noASSIGN) - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); if (!m_pParser->HasBuiltInOprt()) continue; if (m_iSynFlags & noOPT) { @@ -276,7 +279,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { // their identifiers if (IsInfixOpTok(a_Tok)) return true; - Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]); } m_iSynFlags = @@ -284,7 +287,7 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { break; case cmBO: - if (m_iSynFlags & noBO) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noBO) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); if (m_lastTok.GetCode() == cmFUNC) m_iSynFlags = @@ -297,21 +300,23 @@ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok) { break; case cmBC: - if (m_iSynFlags & noBC) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noBC) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN; - if (--m_iBrackets < 0) Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); + if (--m_iBrackets < 0) return Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]); break; case cmELSE: - if (m_iSynFlags & noELSE) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noELSE) + return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; break; case cmIF: - if (m_iSynFlags & noIF) Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); + if (m_iSynFlags & noIF) + return Error(ecUNEXPECTED_CONDITIONAL, m_iPos, pOprtDef[i]); m_iSynFlags = noBC | noPOSTOP | noEND | noOPT | noIF | noELSE; break; @@ -340,7 +345,7 @@ bool ParserTokenReader::IsArgSep(token_type &a_Tok) { szSep[0] = m_cArgSep; szSep[1] = 0; - if (m_iSynFlags & noARG_SEP) Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); + if (m_iSynFlags & noARG_SEP) return Error(ecUNEXPECTED_ARG_SEP, m_iPos, szSep); m_iSynFlags = noBC | noOPT | noEND | noARG_SEP | noPOSTOP | noASSIGN; m_iPos++; @@ -363,9 +368,9 @@ bool ParserTokenReader::IsEOF(token_type &a_Tok) { // check for EOF if (!szFormula[m_iPos] /*|| szFormula[m_iPos] == '\n'*/) { - if (m_iSynFlags & noEND) Error(ecUNEXPECTED_EOF, m_iPos); + if (m_iSynFlags & noEND) return Error(ecUNEXPECTED_EOF, m_iPos); - if (m_iBrackets > 0) Error(ecMISSING_PARENS, m_iPos, _T(")")); + if (m_iBrackets > 0) return Error(ecMISSING_PARENS, m_iPos, _T(")")); m_iSynFlags = 0; a_Tok.Set(cmEND); @@ -392,7 +397,8 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) { a_Tok.Set(it->second, it->first); m_iPos += (int)it->first.length(); - if (m_iSynFlags & noINFIXOP) Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + if (m_iSynFlags & noINFIXOP) + return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; return true; @@ -405,7 +411,7 @@ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok) { m_iPos = (int)iEnd; if (m_iSynFlags & noINFIXOP) - Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN; return true; @@ -435,7 +441,8 @@ bool ParserTokenReader::IsFunTok(token_type &a_Tok) { m_iPos = (int)iEnd; if (m_iSynFlags & noFUN) - Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), a_Tok.GetAsString()); + return Error(ecUNEXPECTED_FUN, m_iPos - (int)a_Tok.GetAsString().length(), + a_Tok.GetAsString()); m_iSynFlags = noANY ^ noBO; return true; @@ -483,7 +490,7 @@ bool ParserTokenReader::IsOprt(token_type &a_Tok) { else { // nope, no infix operator return false; - // Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); + // return Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString()); } } @@ -562,7 +569,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) { m_iPos = iEnd; a_Tok.SetVal(item->second, strTok); - if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) + return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; return true; @@ -578,7 +586,8 @@ bool ParserTokenReader::IsValTok(token_type &a_Tok) { // 2013-11-27 Issue 2: https://code.google.com/p/muparser/issues/detail?id=2 strTok.assign(m_strFormula.c_str(), iStart, m_iPos - iStart); - if (m_iSynFlags & noVAL) Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); + if (m_iSynFlags & noVAL) + return Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok); a_Tok.SetVal(fVal, strTok); m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN; @@ -604,7 +613,7 @@ bool ParserTokenReader::IsVarTok(token_type &a_Tok) { varmap_type::const_iterator item = m_pVarDef->find(strTok); if (item == m_pVarDef->end()) return false; - if (m_iSynFlags & noVAR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noVAR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_pParser->OnDetectVar(&m_strFormula, m_iPos, iEnd); @@ -630,7 +639,7 @@ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok) { strmap_type::const_iterator item = m_pStrVarDef->find(strTok); if (item == m_pStrVarDef->end()) return false; - if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_VAR, m_iPos, strTok); + if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_VAR, m_iPos, strTok); m_iPos = iEnd; if (!m_pParser->m_vStringVarBuf.size()) assert(0 && "muParser internal error"); @@ -658,7 +667,7 @@ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok) { // token identifier. // related bug report: // http://sourceforge.net/tracker/index.php?func=detail&aid=1578779&group_id=137191&atid=737979 - Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); + return Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok); } // If a factory is available implicitely create new variables @@ -706,11 +715,11 @@ bool ParserTokenReader::IsString(token_type &a_Tok) { iSkip++; } - if (iEnd == string_type::npos) Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); + if (iEnd == string_type::npos) return Error(ecUNTERMINATED_STRING, m_iPos, _T("\"")); string_type strTok(strBuf.begin(), strBuf.begin() + iEnd); - if (m_iSynFlags & noSTR) Error(ecUNEXPECTED_STR, m_iPos, strTok); + if (m_iSynFlags & noSTR) return Error(ecUNEXPECTED_STR, m_iPos, strTok); m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());