fix for sets containing recursive records

This commit is contained in:
Vern Paxson 2022-04-29 17:10:48 -07:00
parent aa5a5b2136
commit f7581437d9
2 changed files with 26 additions and 11 deletions

View file

@ -1367,7 +1367,10 @@ static void table_entry_val_delete_func(void* val)
delete tv;
}
static void find_nested_record_types(const TypePtr& t, std::set<RecordType*>* found)
// Third argument tracks records currently being analyzed, to avoid infinite
// loops in the face of recursive records.
static void find_nested_record_types(const TypePtr& t, std::set<RecordType*>* found,
std::set<const RecordType*>* analyzed_records)
{
if ( ! t )
return;
@ -1377,31 +1380,38 @@ static void find_nested_record_types(const TypePtr& t, std::set<RecordType*>* fo
case TYPE_RECORD:
{
auto rt = t->AsRecordType();
if ( analyzed_records->count(rt) > 0 )
return;
analyzed_records->insert(rt);
found->emplace(rt);
for ( auto i = 0; i < rt->NumFields(); ++i )
find_nested_record_types(rt->FieldDecl(i)->type, found);
find_nested_record_types(rt->FieldDecl(i)->type, found, analyzed_records);
analyzed_records->erase(rt);
}
return;
case TYPE_TABLE:
find_nested_record_types(t->AsTableType()->GetIndices(), found);
find_nested_record_types(t->AsTableType()->Yield(), found);
find_nested_record_types(t->AsTableType()->GetIndices(), found, analyzed_records);
find_nested_record_types(t->AsTableType()->Yield(), found, analyzed_records);
return;
case TYPE_LIST:
{
for ( const auto& type : t->AsTypeList()->GetTypes() )
find_nested_record_types(type, found);
find_nested_record_types(type, found, analyzed_records);
}
return;
case TYPE_FUNC:
find_nested_record_types(t->AsFuncType()->Params(), found);
find_nested_record_types(t->AsFuncType()->Yield(), found);
find_nested_record_types(t->AsFuncType()->Params(), found, analyzed_records);
find_nested_record_types(t->AsFuncType()->Yield(), found, analyzed_records);
return;
case TYPE_VECTOR:
find_nested_record_types(t->AsVectorType()->Yield(), found);
find_nested_record_types(t->AsVectorType()->Yield(), found, analyzed_records);
return;
case TYPE_TYPE:
find_nested_record_types(t->AsTypeType()->GetType(), found);
find_nested_record_types(t->AsTypeType()->GetType(), found, analyzed_records);
return;
default:
return;
@ -1419,9 +1429,10 @@ TableVal::TableVal(TableTypePtr t, detail::AttributesPtr a) : Val(t)
for ( const auto& t : table_type->GetIndexTypes() )
{
std::set<RecordType*> found;
std::set<const RecordType*> analyzed_records;
// TODO: this likely doesn't have to be repeated for each new TableVal,
// can remember the resulting dependencies per TableType
find_nested_record_types(t, &found);
find_nested_record_types(t, &found, &analyzed_records);
for ( auto rt : found )
parse_time_table_record_dependencies[rt].emplace_back(NewRef{}, this);

View file

@ -1,4 +1,4 @@
# @TEST-EXEC: zeek -b %INPUT >output 2>&1
# @TEST-EXEC: zeek %INPUT >output 2>&1
# @TEST-EXEC: btest-diff output
# Make sure a set can be indexed with a record that has optional fields
@ -53,3 +53,7 @@ event zeek_init()
print f3 in set_of_foo;
}
# Also make sure that we can declare sets of recursive records.
# This used to crash in Zeek 4.x.
global crash_me: set[Conn::RemovalHook];