Skip to content

Commit

Permalink
lexer: fix Parse() memleaks on invalid regexps
Browse files Browse the repository at this point in the history
Parse() uses bison to parse regexps strings.
bison clears its own state stack before exiting from yyparse().
But bison don't support C++ exceptions so its state remains
uncleared if an exception is thrown from its yylex() or yyerror()
callbacks.

So, we have to delay a Pire::Error exception & re-throw it just after
exiting from yyparse().

Delaying exceptions other than Pire::Error is out of scope of the fix.
  • Loading branch information
sorc1 committed Apr 1, 2016
1 parent 8f1407a commit a2daa4c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 8 deletions.
4 changes: 4 additions & 0 deletions pire/re_lexer.h
Expand Up @@ -146,6 +146,9 @@ class Lexer {

const Pire::Encoding& Encoding() const { return *m_encoding; }
Lexer& SetEncoding(const Pire::Encoding& encoding) { m_encoding = &encoding; return *this; }
void SetError(const char* msg) { errmsg = msg; }
void SetError(ystring msg) { errmsg = msg; }
ystring& GetError() { return errmsg; }

Any& Retval() { return m_retval; }

Expand All @@ -168,6 +171,7 @@ class Lexer {
const Pire::Encoding* m_encoding;
yvector<Feature*> m_features;
Any m_retval;
ystring errmsg;

friend class Feature;

Expand Down
40 changes: 32 additions & 8 deletions pire/re_parser.y
Expand Up @@ -158,18 +158,28 @@ term

int yylex(YYSTYPE* lval, Pire::Lexer& rlex)
{
Pire::Term term = rlex.Lex();
if (!term.Value().Empty())
*lval = new Any(term.Value());
return term.Type();
try {
Pire::Term term = rlex.Lex();
if (!term.Value().Empty())
*lval = new Any(term.Value());
return term.Type();
} catch (Pire::Error &e) {
rlex.SetError(e.what());
return 0;
}
}

void yyerror(const char* str)
{
throw Error((ystring("Regexp parse error: ") + ystring(str)));
}

void yyerror(Pire::Lexer&, const char* str) { yyerror(str); }
void yyerror(Pire::Lexer& rlex, const char* str)
{
if (rlex.GetError().length() == 0)
rlex.SetError(ystring("Regexp parse error: ").append(str));

yyerror(str);
}

void AppendRange(const Encoding& encoding, Fsm& a, const Term::CharacterRange& cr)
{
Expand Down Expand Up @@ -234,13 +244,27 @@ static int yyparse(void*, Pire::Lexer& rlex);

namespace Pire {
namespace Impl {
int yre_parse(Pire::Lexer& rlex) { return yyparse(0, rlex); }
int yre_parse(Pire::Lexer& rlex)
{
int rc = yyparse(0, rlex);

if (rlex.GetError().length() != 0)
throw Error(rlex.GetError());
return rc;
}
}
}
#else
namespace Pire {
namespace Impl {
int yre_parse(Pire::Lexer& rlex) { return yyparse(rlex); }
int yre_parse(Pire::Lexer& rlex)
{
int rc = yyparse(rlex);

if (rlex.GetError().length() != 0)
throw Error(rlex.GetError());
return rc;
}
}
}
#endif

0 comments on commit a2daa4c

Please sign in to comment.