From 2fa1ea77e4e861a9e27e89a1cff07396d3fefd26 Mon Sep 17 00:00:00 2001 From: Vern Paxson Date: Tue, 26 Jun 2018 10:43:06 -0700 Subject: [PATCH] fixed 3 leaks in creating pattern values --- src/NFA.cc | 17 +++++++++++++++-- src/NFA.h | 8 ++++++++ src/RE.cc | 20 ++++++++++++++++++-- src/re-scan.l | 9 ++++++++- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/NFA.cc b/src/NFA.cc index 8fb78a7131..c53aa4304b 100644 --- a/src/NFA.cc +++ b/src/NFA.cc @@ -12,6 +12,7 @@ NFA_State::NFA_State(int arg_sym, EquivClass* ec) sym = arg_sym; ccl = 0; accept = NO_ACCEPT; + first_trans_is_back_ref = false; mark = 0; epsclosure = 0; id = ++nfa_state_id; @@ -33,6 +34,7 @@ NFA_State::NFA_State(CCL* arg_ccl) sym = SYM_CCL; ccl = arg_ccl; accept = NO_ACCEPT; + first_trans_is_back_ref = false; mark = 0; id = ++nfa_state_id; epsclosure = 0; @@ -41,7 +43,8 @@ NFA_State::NFA_State(CCL* arg_ccl) NFA_State::~NFA_State() { for ( int i = 0; i < xtions.length(); ++i ) - Unref(xtions[i]); + if ( i > 0 || ! first_trans_is_back_ref ) + Unref(xtions[i]); delete epsclosure; } @@ -247,7 +250,10 @@ void NFA_Machine::MakePositiveClosure() { AppendEpsilon(); final_state->AddXtion(first_state); - Ref(first_state); + + // Don't Ref the state the final epsilon points to, otherwise we'll + // have reference cycles that lead to leaks. + final_state->SetFirstTransIsBackRef(); } void NFA_Machine::MakeRepl(int lower, int upper) @@ -307,6 +313,13 @@ NFA_Machine* make_alternate(NFA_Machine* m1, NFA_Machine* m2) m2->AppendState(last); Ref(last); + // Keep these around. + Ref(m1->FirstState()); + Ref(m2->FirstState()); + + Unref(m1); + Unref(m2); + return new NFA_Machine(first, last); } diff --git a/src/NFA.h b/src/NFA.h index 560f0930b4..79c3961dd5 100644 --- a/src/NFA.h +++ b/src/NFA.h @@ -46,6 +46,8 @@ public: NFA_State* Mark() const { return mark; } void ClearMarks(); + void SetFirstTransIsBackRef() { first_trans_is_back_ref = true; } + int TransSym() const { return sym; } CCL* TransCCL() const { return ccl; } int ID() const { return id; } @@ -62,7 +64,13 @@ protected: int sym; // if SYM_CCL, then use ccl CCL* ccl; // if nil, then use sym int accept; + + // Whether the first transition points backwards. Used + // to avoid reference-counting loops. + bool first_trans_is_back_ref; + int id; // number that uniquely identifies this state + NFA_state_list xtions; NFA_state_list* epsclosure; NFA_State* mark; diff --git a/src/RE.cc b/src/RE.cc index a4294e064d..4d26ce2423 100644 --- a/src/RE.cc +++ b/src/RE.cc @@ -19,6 +19,7 @@ int case_insensitive = 0; extern int RE_parse(void); extern void RE_set_input(const char* str); +extern void RE_done_with_scan(); Specific_RE_Matcher::Specific_RE_Matcher(match_type arg_mt, int arg_multiline) : equiv_class(NUM_SYM) @@ -108,9 +109,15 @@ int Specific_RE_Matcher::Compile(int lazy) rem = this; RE_set_input(pattern_text); - if ( RE_parse() ) + + int parse_status = RE_parse(); + RE_done_with_scan(); + + if ( parse_status ) { reporter->Error("error compiling pattern /%s/", pattern_text); + Unref(nfa); + nfa = 0; return 0; } @@ -139,9 +146,18 @@ int Specific_RE_Matcher::CompileSet(const string_list& set, const int_list& idx) loop_over_list(set, i) { RE_set_input(set[i]); - if ( RE_parse() ) + int parse_status = RE_parse(); + RE_done_with_scan(); + + if ( parse_status ) { reporter->Error("error compiling pattern /%s/", set[i]); + + if ( set_nfa != nfa ) + Unref(set_nfa); + Unref(nfa); + nfa = 0; + return 0; } diff --git a/src/re-scan.l b/src/re-scan.l index 0d737f08a6..8bd00c8bba 100644 --- a/src/re-scan.l +++ b/src/re-scan.l @@ -196,8 +196,15 @@ CCL_EXPR ("[:"[[:alpha:]]+":]") %% +YY_BUFFER_STATE RE_buf; + void RE_set_input(const char* str) { RE_parse_input = str; - yy_scan_string(str); + RE_buf = yy_scan_string(str); + } + +void RE_done_with_scan() + { + yy_delete_buffer(RE_buf); }