From 8ce2f16759e4fd98df64e7e6ad6b492599c57909 Mon Sep 17 00:00:00 2001 From: Eivind Kvedalen Date: Tue, 8 Mar 2016 00:30:21 +0100 Subject: [PATCH] Expressions: Added code to throw under/overflow exceptions. --- src/App/Expression.cpp | 17 ++++++++++++++--- src/App/ExpressionParser.l | 9 ++++++++- src/App/lex.ExpressionParser.c | 29 ++++++++++++++++++----------- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/App/Expression.cpp b/src/App/Expression.cpp index 0275cc702922..286d07f0e3af 100644 --- a/src/App/Expression.cpp +++ b/src/App/Expression.cpp @@ -1334,7 +1334,13 @@ double num_change(char* yytext,char dez_delim,char grp_delim) } temp[i] = '\0'; - ret_val = atof( temp ); + errno = 0; + ret_val = strtod( temp, NULL ); + if (ret_val == 0 && errno == ERANGE) + throw Base::Exception("Number underflow."); + if (ret_val == HUGE_VAL || ret_val == -HUGE_VAL) + throw Base::Exception("Number overflow."); + return ret_val; } @@ -1409,8 +1415,13 @@ std::vector > tokenize(const std::string &st int token; column = 0; - while ( (token = ExpressionParserlex()) != 0) - result.push_back(boost::make_tuple(token, ExpressionParser::last_column, yytext)); + try { + while ( (token = ExpressionParserlex()) != 0) + result.push_back(boost::make_tuple(token, ExpressionParser::last_column, yytext)); + } + catch (...) { + // Ignore all exceptions + } ExpressionParser_delete_buffer(buf); return result; diff --git a/src/App/ExpressionParser.l b/src/App/ExpressionParser.l index 0fae78c23e53..050f3fe57730 100644 --- a/src/App/ExpressionParser.l +++ b/src/App/ExpressionParser.l @@ -248,7 +248,14 @@ EXPO [eE][-+]?[0-9]+ {DIGIT}*"."{DIGIT}+{EXPO}? COUNT; yylval.fvalue = num_change(yytext,'.',','); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}*","{DIGIT}+{EXPO}? COUNT; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; {DIGIT}+{EXPO} COUNT; yylval.fvalue = num_change(yytext,',','.'); return yylval.fvalue == 1 ? ONE : NUM; -{DIGIT}+ COUNT; yylval.ivalue = strtoll( yytext, NULL, 0 ); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; +{DIGIT}+ { COUNT; + yylval.ivalue = strtoll( yytext, NULL, 0 ); + if (yylval.ivalue == LLONG_MIN) + throw Base::Exception("Integer underflow"); + else if (yylval.ivalue == LLONG_MAX) + throw Base::Exception("Integer overflow"); + if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; + } "pi" COUNT; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi "e" COUNT; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e diff --git a/src/App/lex.ExpressionParser.c b/src/App/lex.ExpressionParser.c index 9543f8acc217..bcef091805d7 100644 --- a/src/App/lex.ExpressionParser.c +++ b/src/App/lex.ExpressionParser.c @@ -6304,36 +6304,43 @@ COUNT; yylval.fvalue = num_change(ExpressionParsertext,',','.'); return yy case 83: YY_RULE_SETUP #line 251 "ExpressionParser.l" -COUNT; yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 ); if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; +{ COUNT; + yylval.ivalue = strtoll( ExpressionParsertext, NULL, 0 ); + if (yylval.ivalue == LLONG_MIN) + throw Base::Exception("Integer underflow"); + else if (yylval.ivalue == LLONG_MAX) + throw Base::Exception("Integer overflow"); + if (yylval.ivalue == 1) { yylval.fvalue = 1; return ONE; } else return INTEGER; + } YY_BREAK case 84: YY_RULE_SETUP -#line 253 "ExpressionParser.l" +#line 260 "ExpressionParser.l" COUNT; yylval.constant.fvalue = M_PI; yylval.constant.name = "pi"; return CONSTANT; // constant pi YY_BREAK case 85: YY_RULE_SETUP -#line 254 "ExpressionParser.l" +#line 261 "ExpressionParser.l" COUNT; yylval.constant.fvalue = M_E; yylval.constant.name = "e"; return CONSTANT; // constant e YY_BREAK case 86: YY_RULE_SETUP -#line 256 "ExpressionParser.l" +#line 263 "ExpressionParser.l" COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS; YY_BREAK case 87: YY_RULE_SETUP -#line 257 "ExpressionParser.l" +#line 264 "ExpressionParser.l" COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS; YY_BREAK case 88: YY_RULE_SETUP -#line 258 "ExpressionParser.l" +#line 265 "ExpressionParser.l" COUNT; yylval.string = ExpressionParsertext; return CELLADDRESS; YY_BREAK case 89: YY_RULE_SETUP -#line 260 "ExpressionParser.l" +#line 267 "ExpressionParser.l" { COUNT; std::string s = ExpressionParsertext; @@ -6351,15 +6358,15 @@ YY_RULE_SETUP YY_BREAK case 90: YY_RULE_SETUP -#line 275 "ExpressionParser.l" +#line 282 "ExpressionParser.l" COUNT; yylval.string = ExpressionParsertext; return IDENTIFIER; YY_BREAK case 91: YY_RULE_SETUP -#line 276 "ExpressionParser.l" +#line 283 "ExpressionParser.l" ECHO; YY_BREAK -#line 6363 "lex.ExpressionParser.c" +#line 6370 "lex.ExpressionParser.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -7317,4 +7324,4 @@ void ExpressionParserfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 276 "ExpressionParser.l" +#line 283 "ExpressionParser.l"