fixed 3 leaks in creating pattern values

This commit is contained in:
Vern Paxson 2018-06-26 10:43:06 -07:00
parent 610d1ae407
commit 2fa1ea77e4
4 changed files with 49 additions and 5 deletions

View file

@ -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,6 +43,7 @@ NFA_State::NFA_State(CCL* arg_ccl)
NFA_State::~NFA_State()
{
for ( int i = 0; i < xtions.length(); ++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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}