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; 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 ) if ( ! t )
return; return;
@ -1377,31 +1380,38 @@ static void find_nested_record_types(const TypePtr& t, std::set<RecordType*>* fo
case TYPE_RECORD: case TYPE_RECORD:
{ {
auto rt = t->AsRecordType(); auto rt = t->AsRecordType();
if ( analyzed_records->count(rt) > 0 )
return;
analyzed_records->insert(rt);
found->emplace(rt); found->emplace(rt);
for ( auto i = 0; i < rt->NumFields(); ++i ) 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; return;
case TYPE_TABLE: case TYPE_TABLE:
find_nested_record_types(t->AsTableType()->GetIndices(), found); find_nested_record_types(t->AsTableType()->GetIndices(), found, analyzed_records);
find_nested_record_types(t->AsTableType()->Yield(), found); find_nested_record_types(t->AsTableType()->Yield(), found, analyzed_records);
return; return;
case TYPE_LIST: case TYPE_LIST:
{ {
for ( const auto& type : t->AsTypeList()->GetTypes() ) for ( const auto& type : t->AsTypeList()->GetTypes() )
find_nested_record_types(type, found); find_nested_record_types(type, found, analyzed_records);
} }
return; return;
case TYPE_FUNC: case TYPE_FUNC:
find_nested_record_types(t->AsFuncType()->Params(), found); find_nested_record_types(t->AsFuncType()->Params(), found, analyzed_records);
find_nested_record_types(t->AsFuncType()->Yield(), found); find_nested_record_types(t->AsFuncType()->Yield(), found, analyzed_records);
return; return;
case TYPE_VECTOR: case TYPE_VECTOR:
find_nested_record_types(t->AsVectorType()->Yield(), found); find_nested_record_types(t->AsVectorType()->Yield(), found, analyzed_records);
return; return;
case TYPE_TYPE: case TYPE_TYPE:
find_nested_record_types(t->AsTypeType()->GetType(), found); find_nested_record_types(t->AsTypeType()->GetType(), found, analyzed_records);
return; return;
default: default:
return; return;
@ -1419,9 +1429,10 @@ TableVal::TableVal(TableTypePtr t, detail::AttributesPtr a) : Val(t)
for ( const auto& t : table_type->GetIndexTypes() ) for ( const auto& t : table_type->GetIndexTypes() )
{ {
std::set<RecordType*> found; std::set<RecordType*> found;
std::set<const RecordType*> analyzed_records;
// TODO: this likely doesn't have to be repeated for each new TableVal, // TODO: this likely doesn't have to be repeated for each new TableVal,
// can remember the resulting dependencies per TableType // 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 ) for ( auto rt : found )
parse_time_table_record_dependencies[rt].emplace_back(NewRef{}, this); 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 # @TEST-EXEC: btest-diff output
# Make sure a set can be indexed with a record that has optional fields # 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; 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];