Coverage Report

Created: 2025-06-24 07:14

/src/zeek/src/file_analysis/AnalyzerSet.cc
Line
Count
Source (jump to first uncovered line)
1
// See the file "COPYING" in the main distribution directory for copyright.
2
3
#include "zeek/file_analysis/AnalyzerSet.h"
4
5
#include "zeek/CompHash.h"
6
#include "zeek/Val.h"
7
#include "zeek/file_analysis/Analyzer.h"
8
#include "zeek/file_analysis/File.h"
9
#include "zeek/file_analysis/Manager.h"
10
11
namespace zeek::file_analysis::detail {
12
13
0
static void analyzer_del_func(void* v) {
14
0
    file_analysis::Analyzer* a = (file_analysis::Analyzer*)v;
15
16
0
    a->Done();
17
0
    delete a;
18
0
}
19
20
936k
AnalyzerSet::AnalyzerSet(File* arg_file) : file(arg_file) { analyzer_map.SetDeleteFunc(analyzer_del_func); }
21
22
936k
AnalyzerSet::~AnalyzerSet() {
23
936k
    while ( ! mod_queue.empty() ) {
24
0
        Modification* mod = mod_queue.front();
25
0
        mod->Abort();
26
0
        delete mod;
27
0
        mod_queue.pop();
28
0
    }
29
936k
}
30
31
0
Analyzer* AnalyzerSet::Find(const zeek::Tag& tag, RecordValPtr args) {
32
0
    auto key = GetKey(tag, std::move(args));
33
0
    Analyzer* rval = analyzer_map.Lookup(key.get());
34
0
    return rval;
35
0
}
36
37
0
bool AnalyzerSet::Add(const zeek::Tag& tag, RecordValPtr args) {
38
0
    auto key = GetKey(tag, args);
39
40
0
    if ( analyzer_map.Lookup(key.get()) ) {
41
0
        DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Instantiate analyzer %s skipped: already exists", file->GetID().c_str(),
42
0
                file_mgr->GetComponentName(tag).c_str());
43
44
0
        return true;
45
0
    }
46
47
0
    file_analysis::Analyzer* a = InstantiateAnalyzer(tag, std::move(args));
48
49
0
    if ( ! a )
50
0
        return false;
51
52
0
    Insert(a, std::move(key));
53
54
0
    return true;
55
0
}
56
57
3.77M
Analyzer* AnalyzerSet::QueueAdd(const zeek::Tag& tag, RecordValPtr args) {
58
3.77M
    auto key = GetKey(tag, args);
59
3.77M
    file_analysis::Analyzer* a = InstantiateAnalyzer(tag, std::move(args));
60
61
3.77M
    if ( ! a )
62
0
        return nullptr;
63
64
3.77M
    mod_queue.push(new AddMod(a, std::move(key)));
65
66
3.77M
    return a;
67
3.77M
}
68
69
3.77M
bool AnalyzerSet::AddMod::Perform(AnalyzerSet* set) {
70
3.77M
    if ( set->analyzer_map.Lookup(key.get()) ) {
71
842k
        DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s skipped: already exists", a->GetFile()->GetID().c_str(),
72
842k
                file_mgr->GetComponentName(a->Tag()).c_str());
73
74
842k
        Abort();
75
842k
        return true;
76
842k
    }
77
78
2.93M
    set->Insert(a, std::move(key));
79
80
2.93M
    return true;
81
3.77M
}
82
83
842k
void AnalyzerSet::AddMod::Abort() { delete a; }
84
85
0
bool AnalyzerSet::Remove(const zeek::Tag& tag, RecordValPtr args) { return Remove(tag, GetKey(tag, std::move(args))); }
86
87
2.93M
bool AnalyzerSet::Remove(const zeek::Tag& tag, std::unique_ptr<zeek::detail::HashKey> key) {
88
2.93M
    auto a = (file_analysis::Analyzer*)analyzer_map.Remove(key.get());
89
90
2.93M
    if ( ! a ) {
91
0
        DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Skip remove analyzer %s", file->GetID().c_str(),
92
0
                file_mgr->GetComponentName(tag).c_str());
93
0
        return false;
94
0
    }
95
96
2.93M
    DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Remove analyzer %s", file->GetID().c_str(),
97
2.93M
            file_mgr->GetComponentName(tag).c_str());
98
99
2.93M
    a->Done();
100
101
    // We don't delete the analyzer object right here because the remove
102
    // operation may execute at a time when it can still be accessed.
103
    // Instead we let the file know to delete the analyzer later.
104
2.93M
    file->DoneWithAnalyzer(a);
105
106
2.93M
    return true;
107
2.93M
}
108
109
2.93M
bool AnalyzerSet::QueueRemove(const zeek::Tag& tag, RecordValPtr args) {
110
2.93M
    auto key = GetKey(tag, std::move(args));
111
2.93M
    auto rval = analyzer_map.Lookup(key.get());
112
2.93M
    mod_queue.push(new RemoveMod(tag, std::move(key)));
113
2.93M
    return rval;
114
2.93M
}
115
116
2.93M
bool AnalyzerSet::RemoveMod::Perform(AnalyzerSet* set) { return set->Remove(tag, std::move(key)); }
117
118
6.71M
std::unique_ptr<zeek::detail::HashKey> AnalyzerSet::GetKey(const zeek::Tag& t, RecordValPtr args) const {
119
6.71M
    auto lv = make_intrusive<ListVal>(TYPE_ANY);
120
6.71M
    lv->Append(t.AsVal());
121
6.71M
    lv->Append(std::move(args));
122
6.71M
    auto key = file_mgr->GetAnalyzerHash()->MakeHashKey(*lv, true);
123
124
6.71M
    if ( ! key )
125
0
        reporter->InternalError("AnalyzerArgs type mismatch");
126
127
6.71M
    return key;
128
6.71M
}
129
130
3.77M
file_analysis::Analyzer* AnalyzerSet::InstantiateAnalyzer(const Tag& tag, RecordValPtr args) const {
131
3.77M
    auto a = file_mgr->InstantiateAnalyzer(tag, std::move(args), file);
132
133
3.77M
    if ( ! a ) {
134
0
        auto c = file_mgr->Lookup(tag);
135
136
0
        if ( c && ! c->Enabled() )
137
0
            return nullptr;
138
139
0
        reporter->Error("[%s] Failed file analyzer %s instantiation", file->GetID().c_str(),
140
0
                        file_mgr->GetComponentName(tag).c_str());
141
0
        return nullptr;
142
0
    }
143
144
3.77M
    return a;
145
3.77M
}
146
147
2.93M
void AnalyzerSet::Insert(file_analysis::Analyzer* a, std::unique_ptr<zeek::detail::HashKey> key) {
148
2.93M
    DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Add analyzer %s", file->GetID().c_str(),
149
2.93M
            file_mgr->GetComponentName(a->Tag()).c_str());
150
2.93M
    analyzer_map.Insert(key.get(), a);
151
152
2.93M
    a->Init();
153
2.93M
}
154
155
98.1M
void AnalyzerSet::DrainModifications() {
156
98.1M
    if ( mod_queue.empty() )
157
95.5M
        return;
158
159
2.54M
    DBG_LOG(DBG_FILE_ANALYSIS, "[%s] Start analyzer mod queue flush", file->GetID().c_str());
160
6.71M
    do {
161
6.71M
        Modification* mod = mod_queue.front();
162
6.71M
        mod->Perform(this);
163
6.71M
        delete mod;
164
6.71M
        mod_queue.pop();
165
6.71M
    } while ( ! mod_queue.empty() );
166
2.54M
    DBG_LOG(DBG_FILE_ANALYSIS, "[%s] End flushing analyzer mod queue.", file->GetID().c_str());
167
2.54M
}
168
169
} // namespace zeek::file_analysis::detail