Fix a crash in expression parser.

Found by lineprinter0@gmail.com through fuzzing.
pull/216/head
whitequark 2017-02-17 02:50:00 +00:00
parent e6ed36f739
commit 41794dbadb
3 changed files with 10 additions and 3 deletions

View File

@ -852,7 +852,7 @@ bool ExprParser::Parse(std::string *error, size_t reduceUntil) {
// sub-expression // sub-expression
if(!Parse(error, /*reduceUntil=*/stack.size())) return false; if(!Parse(error, /*reduceUntil=*/stack.size())) return false;
if(stack.back().type != TokenType::PAREN_RIGHT) { if(stack.empty() || stack.back().type != TokenType::PAREN_RIGHT) {
*error = "Expected ')'"; *error = "Expected ')'";
return false; return false;
} }

View File

@ -107,4 +107,6 @@ TEST_CASE(errors) {
"Expected an operand"); "Expected an operand");
CHECK_PARSE_ERR("( 2 + 2", CHECK_PARSE_ERR("( 2 + 2",
"Expected ')'"); "Expected ')'");
CHECK_PARSE_ERR("(",
"Expected ')'");
} }

View File

@ -9,8 +9,13 @@ int main(int argc, char **argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = InitPlatform(argc, argv);
if(args.size() == 3 && args[1] == "expr") { if(args.size() == 3 && args[1] == "expr") {
std::string expr = args[2]; std::string expr = args[2], err;
fprintf(stderr, "%g\n", Expr::From(expr.c_str(), false)->Eval()); Expr *e = Expr::Parse(expr.c_str(), &err);
if(e == NULL) {
fprintf(stderr, "cannot parse: %s\n", err.c_str());
} else {
fprintf(stderr, "%g\n", e->Eval());
}
FreeAllTemporary(); FreeAllTemporary();
} else { } else {
fprintf(stderr, "Usage: %s <command> <options>\n", args[0].c_str()); fprintf(stderr, "Usage: %s <command> <options>\n", args[0].c_str());