mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 16:48:19 +00:00
Fix use-after-free in some cases of reassigning a table index.
Specifically observed when redef'ing the same index of a table that uses subnets as indices, though the bug seems like it applies more generally to anytime TableVal::Assign is provided with just the HashKey parameter and not the index Val. Addresses BIT-1202.
This commit is contained in:
parent
c289a2743b
commit
e616554ab8
3 changed files with 29 additions and 3 deletions
11
src/Val.cc
11
src/Val.cc
|
@ -1471,13 +1471,19 @@ int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
|
||||||
}
|
}
|
||||||
|
|
||||||
TableEntryVal* new_entry_val = new TableEntryVal(new_val);
|
TableEntryVal* new_entry_val = new TableEntryVal(new_val);
|
||||||
|
HashKey k_copy(k->Key(), k->Size(), k->Hash());
|
||||||
TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k, new_entry_val);
|
TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k, new_entry_val);
|
||||||
|
// If the dictionary index already existed, the insert may free up the
|
||||||
|
// memory allocated to the key bytes, so have to assume k is invalid
|
||||||
|
// from here on out.
|
||||||
|
delete k;
|
||||||
|
k = 0;
|
||||||
|
|
||||||
if ( subnets )
|
if ( subnets )
|
||||||
{
|
{
|
||||||
if ( ! index )
|
if ( ! index )
|
||||||
{
|
{
|
||||||
Val* v = RecoverIndex(k);
|
Val* v = RecoverIndex(&k_copy);
|
||||||
subnets->Insert(v, new_entry_val);
|
subnets->Insert(v, new_entry_val);
|
||||||
Unref(v);
|
Unref(v);
|
||||||
}
|
}
|
||||||
|
@ -1489,7 +1495,7 @@ int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
|
||||||
{
|
{
|
||||||
Val* rec_index = 0;
|
Val* rec_index = 0;
|
||||||
if ( ! index )
|
if ( ! index )
|
||||||
index = rec_index = RecoverIndex(k);
|
index = rec_index = RecoverIndex(&k_copy);
|
||||||
|
|
||||||
if ( new_val )
|
if ( new_val )
|
||||||
{
|
{
|
||||||
|
@ -1547,7 +1553,6 @@ int TableVal::Assign(Val* index, HashKey* k, Val* new_val, Opcode op)
|
||||||
if ( old_entry_val && attrs && attrs->FindAttr(ATTR_EXPIRE_CREATE) )
|
if ( old_entry_val && attrs && attrs->FindAttr(ATTR_EXPIRE_CREATE) )
|
||||||
new_entry_val->SetExpireAccess(old_entry_val->ExpireAccessTime());
|
new_entry_val->SetExpireAccess(old_entry_val->ExpireAccessTime());
|
||||||
|
|
||||||
delete k;
|
|
||||||
if ( old_entry_val )
|
if ( old_entry_val )
|
||||||
{
|
{
|
||||||
old_entry_val->Unref();
|
old_entry_val->Unref();
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
[3.0.0.0/8] = 2.0.0.0/8
|
||||||
|
}
|
||||||
|
2.0.0.0/8
|
17
testing/btest/language/redef-same-prefixtable-idx.bro
Normal file
17
testing/btest/language/redef-same-prefixtable-idx.bro
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
# @TEST-EXEC: bro -b %INPUT >out
|
||||||
|
# @TEST-EXEC: btest-diff out
|
||||||
|
|
||||||
|
const my_table: table[subnet] of subnet &redef;
|
||||||
|
|
||||||
|
redef my_table[3.0.0.0/8] = 1.0.0.0/8;
|
||||||
|
redef my_table[3.0.0.0/8] = 2.0.0.0/8;
|
||||||
|
|
||||||
|
# The above is basically a shorthand for:
|
||||||
|
# redef my_table += { [3.0.0.0/8] = 1.0.0.0/8 };
|
||||||
|
# redef my_table += { [3.0.0.0/8] = 2.0.0.0/8 };
|
||||||
|
|
||||||
|
event bro_init()
|
||||||
|
{
|
||||||
|
print my_table;
|
||||||
|
print my_table[3.0.0.0/8];
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue