Fix using clear_table() within an &expire_func

This previously crashed since clear_table()/TableVal::RemoveAll() left
behind a stale iterator to the old table causing a heap-use-after-free
when resuming table expiry iteration in TableVal::DoExpire().
This commit is contained in:
Jon Siwek 2021-04-26 22:45:14 -07:00
parent 76483a9efa
commit d51bd4bc46
3 changed files with 35 additions and 1 deletions

View file

@ -1459,6 +1459,8 @@ TableVal::~TableVal()
void TableVal::RemoveAll() void TableVal::RemoveAll()
{ {
delete expire_iterator;
expire_iterator = nullptr;
// Here we take the brute force approach. // Here we take the brute force approach.
delete table_val; delete table_val;
table_val = new PDict<TableEntryVal>; table_val = new PDict<TableEntryVal>;
@ -2575,6 +2577,10 @@ void TableVal::DoExpire(double t)
if ( ! v ) if ( ! v )
{ // user-provided function deleted it { // user-provided function deleted it
if ( ! expire_iterator )
// Entire table got dropped (e.g. clear_table() / RemoveAll())
break;
continue; continue;
} }
@ -2613,7 +2619,7 @@ void TableVal::DoExpire(double t)
if ( modified ) if ( modified )
Modified(); Modified();
if ( (*expire_iterator) == table_val->end_robust() ) if ( ! expire_iterator || (*expire_iterator) == table_val->end_robust() )
{ {
delete expire_iterator; delete expire_iterator;
expire_iterator = nullptr; expire_iterator = nullptr;

View file

@ -0,0 +1,2 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
expire

View file

@ -0,0 +1,26 @@
# @TEST-EXEC: zeek -b %INPUT > out
# @TEST-EXEC: btest-diff out
# @TEST-DOC: Checks use of clear_table() within an &expire_func works.
redef exit_only_after_terminate=T;
redef table_expire_interval = 1msec;
global myexpire: function(t: table[count] of count, i: count): interval;
global mt: table[count] of count &create_expire=1msec &expire_func=myexpire;
function myexpire(t: table[count] of count, i: count): interval
{
print "expire";
clear_table(mt);
terminate();
return 0secs;
}
event zeek_init()
{
mt[0] = 0;
mt[1] = 1;
mt[2] = 2;
}