Merge pull request #13665 from wwmayer/fix_memory_leak2

Core: fix possible memory leaks when using parser
This commit is contained in:
Chris Hennes
2024-04-29 11:14:11 -05:00
committed by GitHub
2 changed files with 48 additions and 9 deletions

View File

@@ -3609,6 +3609,27 @@ int ExpressionParserlex();
#include "lex.ExpressionParser.c"
#endif // DOXYGEN_SHOULD_SKIP_THIS
class StringBufferCleaner
{
public:
explicit StringBufferCleaner(YY_BUFFER_STATE buffer)
: my_string_buffer {buffer}
{}
~StringBufferCleaner()
{
// free the scan buffer
yy_delete_buffer(my_string_buffer);
}
StringBufferCleaner(const StringBufferCleaner&) = delete;
StringBufferCleaner(StringBufferCleaner&&) = delete;
StringBufferCleaner& operator=(const StringBufferCleaner&) = delete;
StringBufferCleaner& operator=(StringBufferCleaner&&) = delete;
private:
YY_BUFFER_STATE my_string_buffer;
};
#if defined(__clang__)
# pragma clang diagnostic pop
#elif defined (__GNUC__)
@@ -3710,6 +3731,7 @@ static void initParser(const App::DocumentObject *owner)
std::vector<std::tuple<int, int, std::string> > tokenize(const std::string &str)
{
ExpressionParser::YY_BUFFER_STATE buf = ExpressionParser_scan_string(str.c_str());
ExpressionParser::StringBufferCleaner cleaner(buf);
std::vector<std::tuple<int, int, std::string> > result;
int token;
@@ -3722,7 +3744,6 @@ std::vector<std::tuple<int, int, std::string> > tokenize(const std::string &str)
// Ignore all exceptions
}
ExpressionParser_delete_buffer(buf);
return result;
}
@@ -3745,15 +3766,13 @@ Expression * App::ExpressionParser::parse(const App::DocumentObject *owner, cons
{
// parse from buffer
ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer);
ExpressionParser::StringBufferCleaner cleaner(my_string_buffer);
initParser(owner);
// run the parser
int result = ExpressionParser::ExpressionParser_yyparse ();
// free the scan buffer
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);
if (result != 0)
throw ParserError("Failed to parse expression.");
@@ -3772,15 +3791,13 @@ UnitExpression * ExpressionParser::parseUnit(const App::DocumentObject *owner, c
{
// parse from buffer
ExpressionParser::YY_BUFFER_STATE my_string_buffer = ExpressionParser::ExpressionParser_scan_string (buffer);
ExpressionParser::StringBufferCleaner cleaner(my_string_buffer);
initParser(owner);
// run the parser
int result = ExpressionParser::ExpressionParser_yyparse ();
// free the scan buffer
ExpressionParser::ExpressionParser_delete_buffer (my_string_buffer);
if (result != 0)
throw ParserError("Failed to parse expression.");
@@ -3823,9 +3840,9 @@ namespace {
std::tuple<int, int> getTokenAndStatus(const std::string & str)
{
ExpressionParser::YY_BUFFER_STATE buf = ExpressionParser::ExpressionParser_scan_string(str.c_str());
ExpressionParser::StringBufferCleaner cleaner(buf);
int token = ExpressionParser::ExpressionParserlex();
int status = ExpressionParser::ExpressionParserlex();
ExpressionParser::ExpressionParser_delete_buffer(buf);
return std::make_tuple(token, status);
}

View File

@@ -297,12 +297,35 @@ int SelectionFilterlex();
# pragma GCC diagnostic pop
#endif
#endif // DOXYGEN_SHOULD_SKIP_THIS
class StringBufferCleaner
{
public:
explicit StringBufferCleaner(YY_BUFFER_STATE buffer)
: my_string_buffer {buffer}
{}
~StringBufferCleaner()
{
// free the scan buffer
yy_delete_buffer(my_string_buffer);
}
StringBufferCleaner(const StringBufferCleaner&) = delete;
StringBufferCleaner(StringBufferCleaner&&) = delete;
StringBufferCleaner& operator=(const StringBufferCleaner&) = delete;
StringBufferCleaner& operator=(StringBufferCleaner&&) = delete;
private:
YY_BUFFER_STATE my_string_buffer;
};
}
bool SelectionFilter::parse()
{
Errors = "";
SelectionParser::YY_BUFFER_STATE my_string_buffer = SelectionParser::SelectionFilter_scan_string (Filter.c_str());
SelectionParser::StringBufferCleaner cleaner(my_string_buffer);
// be aware that this parser is not reentrant! Don't use with Threats!!!
assert(!ActFilter);
ActFilter = this;
@@ -310,7 +333,6 @@ bool SelectionFilter::parse()
ActFilter = nullptr;
Ast.reset(TopBlock);
TopBlock = nullptr;
SelectionParser::SelectionFilter_delete_buffer (my_string_buffer);
SelectionParser::StringFactory::instance()->clear();
if (Errors.empty()) {