From ef4f74aa942f385f3a944edc11ceba9ebde0720b Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 22 Apr 2021 23:16:03 +0200 Subject: [PATCH] Gui: fix memory leak in SelectionParser::yyparse() --- src/Gui/SelectionFilter.cpp | 26 ++++++++++++++++++++++++++ src/Gui/SelectionFilter.h | 4 +--- src/Gui/SelectionFilter.l | 2 +- src/Gui/SelectionFilter.tab.c | 2 +- src/Gui/SelectionFilter.y | 22 +++++++++++----------- src/Gui/lex.SelectionFilter.c | 2 +- 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/Gui/SelectionFilter.cpp b/src/Gui/SelectionFilter.cpp index dd4e2d89d91b..5c6d26a59028 100644 --- a/src/Gui/SelectionFilter.cpp +++ b/src/Gui/SelectionFilter.cpp @@ -363,6 +363,31 @@ int fileno(FILE *stream) {return _fileno(stream);} namespace SelectionParser { +/*! + * \brief The StringFactory class + * Helper class to record the created strings used by the parser. + */ +class StringFactory { + std::list> data; + std::size_t max_elements = 20; +public: + static StringFactory* instance() { + static StringFactory* inst = new StringFactory(); + return inst; + } + std::string* make(const std::string& str) { + data.push_back(std::make_unique(str)); + return data.back().get(); + } + static std::string* New(const std::string& str) { + return StringFactory::instance()->make(str); + } + void clear() { + if (data.size() > max_elements) + data.clear(); + } +}; + // show the parser the lexer method #define yylex SelectionFilterlex int SelectionFilterlex(void); @@ -401,6 +426,7 @@ bool SelectionFilter::parse(void) Ast.reset(TopBlock); TopBlock = 0; SelectionParser::SelectionFilter_delete_buffer (my_string_buffer); + SelectionParser::StringFactory::instance()->clear(); if (Errors.empty()) { return true; diff --git a/src/Gui/SelectionFilter.h b/src/Gui/SelectionFilter.h index 7f625f854ef6..505b0db9c4d9 100644 --- a/src/Gui/SelectionFilter.h +++ b/src/Gui/SelectionFilter.h @@ -207,10 +207,8 @@ struct Node_Object :Slice(slc) { ObjectType = Base::Type::fromName(type->c_str()); - delete (type); - if(subname){ + if (subname) { SubName = *subname; - delete subname; } } ~Node_Object(){ diff --git a/src/Gui/SelectionFilter.l b/src/Gui/SelectionFilter.l index eda00025a775..fe96a20d6b87 100644 --- a/src/Gui/SelectionFilter.l +++ b/src/Gui/SelectionFilter.l @@ -58,7 +58,7 @@ "::" return TNAMESPACE; [a-zA-Z_][a-zA-Z0-9_]* { - yylval.string = new std::string(yytext); + yylval.string = StringFactory::New(yytext); return TIDENTIFIER; } [0-9]+ { diff --git a/src/Gui/SelectionFilter.tab.c b/src/Gui/SelectionFilter.tab.c index 5dabdbc950f4..9d136765b3f6 100644 --- a/src/Gui/SelectionFilter.tab.c +++ b/src/Gui/SelectionFilter.tab.c @@ -1345,7 +1345,7 @@ yyparse () /* Line 1464 of yacc.c */ #line 40 "SelectionFilter.y" - { (yyval.string) = new std::string(*(yyvsp[(2) - (4)].string) + "::" + *(yyvsp[(4) - (4)].string)) ;} + { (yyval.string) = StringFactory::New(*(yyvsp[(2) - (4)].string) + "::" + *(yyvsp[(4) - (4)].string)) ;} break; case 4: diff --git a/src/Gui/SelectionFilter.y b/src/Gui/SelectionFilter.y index 051599e7ed6d..e82d4c109ba7 100644 --- a/src/Gui/SelectionFilter.y +++ b/src/Gui/SelectionFilter.y @@ -55,25 +55,25 @@ -type : TSELECT TIDENTIFIER { $$ = $2 } - | TSELECT TIDENTIFIER TNAMESPACE TIDENTIFIER { $$ = new std::string(*$2 + "::" + *$4) } +type : TSELECT TIDENTIFIER { $$ = $2; } + | TSELECT TIDENTIFIER TNAMESPACE TIDENTIFIER { $$ = StringFactory::New(*$2 + "::" + *$4); } -subname : { $$ = 0 } - | TSUB TIDENTIFIER { $$ = $2 } +subname : { $$ = 0; } + | TSUB TIDENTIFIER { $$ = $2; } -count : { $$ = 0 } - | TCOUNT TNUMBER TSLICE TNUMBER { $$ = new Node_Slice($2,$4) } - | TCOUNT TNUMBER TSLICE { $$ = new Node_Slice($2) } - | TCOUNT TNUMBER { $$ = new Node_Slice($2,$2) } +count : { $$ = 0; } + | TCOUNT TNUMBER TSLICE TNUMBER { $$ = new Node_Slice($2,$4); } + | TCOUNT TNUMBER TSLICE { $$ = new Node_Slice($2); } + | TCOUNT TNUMBER { $$ = new Node_Slice($2,$2); } -matchline : type subname count { $$ = new Node_Object($1,$2,$3) } +matchline : type subname count { $$ = new Node_Object($1,$2,$3); } matchlines : matchline { $$ = new Node_Block($1); } | matchlines matchline { $$ = $1 ; $$->Objects.emplace_back($2); } -block : matchlines { $$ = $1 } +block : matchlines { $$ = $1; } -filter: block { TopBlock = $1 } +filter: block { TopBlock = $1; } ; diff --git a/src/Gui/lex.SelectionFilter.c b/src/Gui/lex.SelectionFilter.c index 1518012aa4f8..4e0c03f462bd 100644 --- a/src/Gui/lex.SelectionFilter.c +++ b/src/Gui/lex.SelectionFilter.c @@ -856,7 +856,7 @@ case 8: YY_RULE_SETUP #line 41 "SelectionFilter.l" { - yylval.string = new std::string(SelectionFiltertext); + yylval.string = StringFactory::New(SelectionFiltertext); return TIDENTIFIER; } YY_BREAK