Analyzer: Add GetChildAnalyzer() and IsPreventedChildAnalyzer()

GetChildAnalyzer() has the same semantics as HasChildAnalyzer(), but returns
the raw pointer to the child analyzer. Main issue is memory management: That
pointer is not guaranteed to stay valid. It might be disabled from script
land or otherwise removed from the analyzer tree and subsequent
deleted in one of the Forward* methods.

IsPreventedChildAnalyzer() provides minimal introspection for prevented
child analyzer tags and allows to remove some duplicated code.
This commit is contained in:
Arne Welzel 2023-03-29 10:28:30 +02:00
parent 2f5b9ce038
commit b03e678438
2 changed files with 42 additions and 16 deletions

View file

@ -386,10 +386,8 @@ void Analyzer::ForwardEndOfData(bool orig)
bool Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init) bool Analyzer::AddChildAnalyzer(Analyzer* analyzer, bool init)
{ {
auto t = analyzer->GetAnalyzerTag(); auto t = analyzer->GetAnalyzerTag();
auto it = std::find(prevented.begin(), prevented.end(), t);
auto prevent = (it != prevented.end());
if ( HasChildAnalyzer(t) || prevent ) if ( HasChildAnalyzer(t) || IsPreventedChildAnalyzer(t) )
{ {
analyzer->Done(); analyzer->Done();
delete analyzer; delete analyzer;
@ -418,9 +416,7 @@ Analyzer* Analyzer::AddChildAnalyzer(const zeek::Tag& analyzer)
if ( HasChildAnalyzer(analyzer) ) if ( HasChildAnalyzer(analyzer) )
return nullptr; return nullptr;
auto it = std::find(prevented.begin(), prevented.end(), analyzer); if ( IsPreventedChildAnalyzer(tag) )
if ( it != prevented.end() )
return nullptr; return nullptr;
Analyzer* a = analyzer_mgr->InstantiateAnalyzer(analyzer, conn); Analyzer* a = analyzer_mgr->InstantiateAnalyzer(analyzer, conn);
@ -468,27 +464,35 @@ bool Analyzer::Remove()
return removing; return removing;
} }
void Analyzer::PreventChildren(zeek::Tag tag) void Analyzer::PreventChildren(const zeek::Tag& tag)
{ {
auto it = std::find(prevented.begin(), prevented.end(), tag); if ( IsPreventedChildAnalyzer(tag) )
if ( it != prevented.end() )
return; return;
prevented.emplace_back(tag); prevented.emplace_back(tag);
} }
bool Analyzer::HasChildAnalyzer(zeek::Tag tag) bool Analyzer::IsPreventedChildAnalyzer(const zeek::Tag& tag) const
{
return std::find(prevented.begin(), prevented.end(), tag) != prevented.end();
}
bool Analyzer::HasChildAnalyzer(const zeek::Tag& tag) const
{
return GetChildAnalyzer(tag) != nullptr;
}
Analyzer* Analyzer::GetChildAnalyzer(const zeek::Tag& tag) const
{ {
LOOP_OVER_CHILDREN(i) LOOP_OVER_CHILDREN(i)
if ( (*i)->tag == tag && ! ((*i)->removing || (*i)->finished) ) if ( (*i)->tag == tag && ! ((*i)->removing || (*i)->finished) )
return true; return *i;
LOOP_OVER_GIVEN_CHILDREN(i, new_children) LOOP_OVER_GIVEN_CHILDREN(i, new_children)
if ( (*i)->tag == tag && ! ((*i)->removing || (*i)->finished) ) if ( (*i)->tag == tag && ! ((*i)->removing || (*i)->finished) )
return true; return *i;
return false; return nullptr;
} }
Analyzer* Analyzer::FindChild(ID arg_id) Analyzer* Analyzer::FindChild(ID arg_id)

View file

@ -434,14 +434,36 @@ public:
* *
* @param tag The type of analyzer to prevent. * @param tag The type of analyzer to prevent.
*/ */
void PreventChildren(zeek::Tag tag); void PreventChildren(const zeek::Tag& tag);
/**
* Returns true if the given analyzer type is prevented from
* being added as a child.
*
* @param tag The type of analyzer to prevent.
*
* @return true if the analyzer type is prevented, else false.
*/
bool IsPreventedChildAnalyzer(const zeek::Tag& tag) const;
/** /**
* Returns true if analyzer has a direct child of a given type. * Returns true if analyzer has a direct child of a given type.
* *
* @param tag The type of analyzer to check for. * @param tag The type of analyzer to check for.
*/ */
bool HasChildAnalyzer(zeek::Tag tag); bool HasChildAnalyzer(const zeek::Tag& tag) const;
/**
* Returns a pointer to a direct child analyzer of the given type.
*
* Note that the returned pointer is owned by the analyzer and may
* be deleted without notification. Do not hold on to it.
*
* @param tag The type of the analyzer to check for.
*
* @return The analyzer, or null if not found.
*/
Analyzer* GetChildAnalyzer(const zeek::Tag& tag) const;
/** /**
* Recursively searches all (direct or indirect) childs of the * Recursively searches all (direct or indirect) childs of the