Coverage Report

Created: 2026-09-21 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/zeek/src/OpaqueVal.cc
Line
Count
Source
1
// See the file "COPYING" in the main distribution directory for copyright.
2
3
// We use deprecated OpenSSL APIs for MD5, SHA1 and SHA256 because there is no API that lets you
4
// store the internal state of hashing functions. For more information, see
5
// https://github.com/zeek/zeek/issues/1379 and https://github.com/openssl/openssl/issues/14222
6
7
#define OPENSSL_SUPPRESS_DEPRECATED
8
9
#include "zeek/OpaqueVal.h"
10
11
#include <broker/data.hh>
12
#include <broker/error.hh>
13
#include <openssl/md5.h>
14
#include <openssl/sha.h>
15
#include <paraglob/exceptions.h>
16
#include <memory>
17
18
#include "zeek/CompHash.h"
19
#include "zeek/Desc.h"
20
#include "zeek/Reporter.h"
21
#include "zeek/Scope.h"
22
#include "zeek/Var.h"
23
#include "zeek/broker/Data.h"
24
#include "zeek/digest.h"
25
#include "zeek/probabilistic/BloomFilter.h"
26
#include "zeek/probabilistic/CardinalityCounter.h"
27
28
29
namespace zeek {
30
31
// Helper to retrieve a broker count out of a list at a specified index, and
32
// casted to the expected destination type.
33
template<typename V, typename D>
34
0
bool get_vector_idx_if_count(V& v, size_t i, D* dst) {
35
0
    if ( i >= v.Size() || ! v[i].IsCount() )
36
0
        return false;
37
38
0
    *dst = static_cast<D>(v[i].ToCount());
39
0
    return true;
40
0
}
Unexecuted instantiation: bool zeek::get_vector_idx_if_count<zeek::BrokerListView, long>(zeek::BrokerListView&, unsigned long, long*)
Unexecuted instantiation: bool zeek::get_vector_idx_if_count<zeek::BrokerListView, int>(zeek::BrokerListView&, unsigned long, int*)
Unexecuted instantiation: bool zeek::get_vector_idx_if_count<zeek::BrokerListView, double>(zeek::BrokerListView&, unsigned long, double*)
Unexecuted instantiation: bool zeek::get_vector_idx_if_count<zeek::BrokerListView, unsigned int>(zeek::BrokerListView&, unsigned long, unsigned int*)
Unexecuted instantiation: bool zeek::get_vector_idx_if_count<zeek::BrokerListView, unsigned char>(zeek::BrokerListView&, unsigned long, unsigned char*)
41
42
1.71k
OpaqueMgr* OpaqueMgr::mgr() {
43
1.71k
    static OpaqueMgr mgr;
44
1.71k
    return &mgr;
45
1.71k
}
46
47
6.20M
OpaqueVal::OpaqueVal(OpaqueTypePtr t) : Val(std::move(t)) {}
48
49
0
const std::string& OpaqueMgr::TypeID(const OpaqueVal* v) const {
50
0
    auto x = _types.find(v->OpaqueName());
51
52
0
    if ( x == _types.end() )
53
0
        reporter->InternalError("OpaqueMgr::TypeID: opaque type %s not registered", v->OpaqueName());
54
55
0
    return x->first;
56
0
}
57
58
0
OpaqueValPtr OpaqueMgr::Instantiate(const std::string& id) const {
59
0
    auto x = _types.find(id);
60
0
    return x != _types.end() ? (*x->second)() : nullptr;
61
0
}
62
63
0
std::optional<BrokerData> OpaqueVal::SerializeData() const {
64
0
    auto type = OpaqueMgr::mgr()->TypeID(this);
65
66
0
    auto d = DoSerializeData();
67
0
    if ( ! d )
68
0
        return std::nullopt;
69
70
0
    BrokerListBuilder builder;
71
0
    builder.Add(std::move(type));
72
0
    builder.Add(std::move(*d));
73
0
    return std::move(builder).Build();
74
0
}
75
76
0
OpaqueValPtr OpaqueVal::UnserializeData(BrokerDataView data) {
77
0
    if ( ! data.IsList() )
78
0
        return nullptr;
79
80
0
    return UnserializeData(data.ToList());
81
0
}
82
83
0
OpaqueValPtr OpaqueVal::UnserializeData(BrokerListView v) {
84
0
    if ( v.Size() != 2 || ! v[0].IsString() )
85
0
        return nullptr;
86
87
0
    auto type = v[0].ToString();
88
89
0
    auto val = OpaqueMgr::mgr()->Instantiate(std::string{type});
90
0
    if ( ! val )
91
0
        return nullptr;
92
93
0
    if ( ! val->DoUnserializeData(v[1]) )
94
0
        return nullptr;
95
96
0
    return val;
97
0
}
98
99
0
std::optional<BrokerData> OpaqueVal::DoSerializeData() const { return std::nullopt; }
100
101
0
bool OpaqueVal::DoUnserializeData(BrokerDataView data) { return false; }
102
103
0
std::optional<BrokerData> OpaqueVal::SerializeType(const TypePtr& t) {
104
0
    if ( t->InternalType() == TYPE_INTERNAL_ERROR )
105
0
        return std::nullopt;
106
107
0
    BrokerListBuilder builder;
108
109
0
    if ( t->InternalType() == TYPE_INTERNAL_OTHER ) {
110
        // Serialize by name.
111
0
        assert(! t->GetName().empty());
112
0
        builder.Add(true);
113
0
        builder.Add(t->GetName());
114
0
    }
115
0
    else {
116
        // A base type.
117
0
        builder.Add(false);
118
0
        builder.Add(static_cast<uint64_t>(t->Tag()));
119
0
    }
120
121
0
    return {std::move(builder).Build()};
122
0
}
123
124
0
TypePtr OpaqueVal::UnserializeType(BrokerDataView data) {
125
0
    if ( ! data.IsList() )
126
0
        return nullptr;
127
128
0
    auto v = data.ToList();
129
130
0
    if ( v.Size() != 2 || ! v[0].IsBool() )
131
0
        return nullptr;
132
133
0
    if ( v[0].ToBool() ) // Get by name?
134
0
    {
135
0
        if ( ! v[1].IsString() )
136
0
            return nullptr;
137
138
0
        const auto& id = detail::global_scope()->Find(v[1].ToString());
139
0
        if ( ! id )
140
0
            return nullptr;
141
142
0
        if ( ! id->IsType() )
143
0
            return nullptr;
144
145
0
        return id->GetType();
146
0
    }
147
148
0
    if ( ! v[1].IsCount() )
149
0
        return nullptr;
150
151
    // Avoid making an out-of-range TypeTag
152
0
    auto tag_raw = v[1].ToCount();
153
0
    if ( tag_raw >= NUM_TYPES )
154
0
        return nullptr;
155
156
0
    return base_type(static_cast<TypeTag>(tag_raw));
157
0
}
158
159
0
ValPtr OpaqueVal::DoClone(CloneState* state) {
160
0
    auto d = OpaqueVal::SerializeData();
161
0
    if ( ! d )
162
0
        return nullptr;
163
164
0
    auto rval = OpaqueVal::UnserializeData(d->AsView());
165
0
    return state->NewClone(this, std::move(rval));
166
0
}
167
168
0
void OpaqueVal::ValDescribe(ODesc* d) const { d->Add(util::fmt("<opaque of %s>", OpaqueName())); }
169
170
0
void OpaqueVal::ValDescribeReST(ODesc* d) const { d->Add(util::fmt("<opaque of %s>", OpaqueName())); }
171
172
208M
bool HashVal::IsValid() const { return valid; }
173
174
6.19M
bool HashVal::Init() {
175
6.19M
    if ( valid )
176
0
        return false;
177
178
6.19M
    valid = DoInit();
179
6.19M
    return valid;
180
6.19M
}
181
182
3.98M
StringValPtr HashVal::Get() {
183
3.98M
    if ( ! valid )
184
0
        return val_mgr->EmptyString();
185
186
3.98M
    auto result = DoGet();
187
3.98M
    valid = false;
188
3.98M
    return result;
189
3.98M
}
190
191
97.3M
bool HashVal::Feed(const void* data, size_t size) {
192
97.3M
    if ( valid )
193
97.3M
        return DoFeed(data, size);
194
195
0
    Error("attempt to update an invalid opaque hash value");
196
0
    return false;
197
97.3M
}
198
199
0
bool HashVal::DoInit() {
200
0
    assert(! "missing implementation of DoInit()");
201
0
    return false;
202
0
}
203
204
0
bool HashVal::DoFeed(const void*, size_t) {
205
0
    assert(! "missing implementation of DoFeed()");
206
0
    return false;
207
0
}
208
209
0
StringValPtr HashVal::DoGet() {
210
0
    assert(! "missing implementation of DoGet()");
211
0
    return val_mgr->EmptyString();
212
0
}
213
214
6.19M
HashVal::HashVal(OpaqueTypePtr t) : OpaqueVal(std::move(t)) { valid = false; }
215
216
namespace {
217
218
constexpr size_t MD5VAL_STATE_SIZE = sizeof(MD5_CTX);
219
220
constexpr size_t SHA1VAL_STATE_SIZE = sizeof(SHA_CTX);
221
222
constexpr size_t SHA224VAL_STATE_SIZE = sizeof(SHA256_CTX);
223
224
constexpr size_t SHA256VAL_STATE_SIZE = sizeof(SHA256_CTX);
225
226
constexpr size_t SHA384VAL_STATE_SIZE = sizeof(SHA512_CTX);
227
228
constexpr size_t SHA512VAL_STATE_SIZE = sizeof(SHA512_CTX);
229
230
// -- MD5
231
232
35.8M
auto* to_native_ptr(MD5Val::StatePtr ptr) { return reinterpret_cast<MD5_CTX*>(ptr); }
233
234
2.06M
void do_init(MD5Val::StatePtr& ptr) {
235
2.06M
    auto ctx = new MD5_CTX;
236
2.06M
    MD5_Init(ctx);
237
2.06M
    ptr = reinterpret_cast<MD5Val::StatePtr>(ctx);
238
2.06M
}
239
240
0
void do_clone(MD5Val::StatePtr out, MD5Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
241
242
32.4M
void do_feed(MD5Val::StatePtr ptr, const void* data, size_t size) { MD5_Update(to_native_ptr(ptr), data, size); }
243
244
1.32M
void do_get(MD5Val::StatePtr ptr, u_char* digest) { MD5_Final(digest, to_native_ptr(ptr)); }
245
246
0
std::string do_serialize(MD5Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(MD5_CTX)}; }
247
248
0
void do_unserialize(MD5Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
249
250
2.06M
void do_destroy(MD5Val::StatePtr ptr) { delete to_native_ptr(ptr); }
251
252
// -- SHA1
253
254
35.8M
auto* to_native_ptr(SHA1Val::StatePtr ptr) { return reinterpret_cast<SHA_CTX*>(ptr); }
255
256
2.06M
void do_init(SHA1Val::StatePtr& ptr) {
257
2.06M
    auto ctx = new SHA_CTX;
258
2.06M
    SHA1_Init(ctx);
259
2.06M
    ptr = reinterpret_cast<SHA1Val::StatePtr>(ctx);
260
2.06M
}
261
262
0
void do_clone(SHA1Val::StatePtr out, SHA1Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
263
264
32.4M
void do_feed(SHA1Val::StatePtr ptr, const void* data, size_t size) { SHA1_Update(to_native_ptr(ptr), data, size); }
265
266
1.32M
void do_get(SHA1Val::StatePtr ptr, u_char* digest) { SHA1_Final(digest, to_native_ptr(ptr)); }
267
268
0
std::string do_serialize(SHA1Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(SHA_CTX)}; }
269
270
0
void do_unserialize(SHA1Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
271
272
2.06M
void do_destroy(SHA1Val::StatePtr ptr) { delete to_native_ptr(ptr); }
273
274
// -- SHA224
275
276
0
auto* to_native_ptr(SHA224Val::StatePtr ptr) { return reinterpret_cast<SHA256_CTX*>(ptr); }
277
278
0
void do_init(SHA224Val::StatePtr& ptr) {
279
0
    auto ctx = new SHA256_CTX;
280
0
    SHA224_Init(ctx);
281
0
    ptr = reinterpret_cast<SHA224Val::StatePtr>(ctx);
282
0
}
283
284
0
void do_clone(SHA224Val::StatePtr out, SHA224Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
285
286
0
void do_feed(SHA224Val::StatePtr ptr, const void* data, size_t size) { SHA224_Update(to_native_ptr(ptr), data, size); }
287
288
0
void do_get(SHA224Val::StatePtr ptr, u_char* digest) { SHA224_Final(digest, to_native_ptr(ptr)); }
289
290
0
std::string do_serialize(SHA224Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(SHA256_CTX)}; }
291
292
0
void do_unserialize(SHA224Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
293
294
0
void do_destroy(SHA224Val::StatePtr ptr) { delete to_native_ptr(ptr); }
295
296
// -- SHA256
297
298
35.8M
auto* to_native_ptr(SHA256Val::StatePtr ptr) { return reinterpret_cast<SHA256_CTX*>(ptr); }
299
300
2.06M
void do_init(SHA256Val::StatePtr& ptr) {
301
2.06M
    auto ctx = new SHA256_CTX;
302
2.06M
    SHA256_Init(ctx);
303
2.06M
    ptr = reinterpret_cast<SHA256Val::StatePtr>(ctx);
304
2.06M
}
305
306
0
void do_clone(SHA256Val::StatePtr out, SHA256Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
307
308
32.4M
void do_feed(SHA256Val::StatePtr ptr, const void* data, size_t size) { SHA256_Update(to_native_ptr(ptr), data, size); }
309
310
1.32M
void do_get(SHA256Val::StatePtr ptr, u_char* digest) { SHA256_Final(digest, to_native_ptr(ptr)); }
311
312
0
std::string do_serialize(SHA256Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(SHA256_CTX)}; }
313
314
0
void do_unserialize(SHA256Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
315
316
2.06M
void do_destroy(SHA256Val::StatePtr ptr) { delete to_native_ptr(ptr); }
317
318
// -- SHA384
319
320
0
auto* to_native_ptr(SHA384Val::StatePtr ptr) { return reinterpret_cast<SHA512_CTX*>(ptr); }
321
322
0
void do_init(SHA384Val::StatePtr& ptr) {
323
0
    auto ctx = new SHA512_CTX;
324
0
    SHA384_Init(ctx);
325
0
    ptr = reinterpret_cast<SHA384Val::StatePtr>(ctx);
326
0
}
327
328
0
void do_clone(SHA384Val::StatePtr out, SHA384Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
329
330
0
void do_feed(SHA384Val::StatePtr ptr, const void* data, size_t size) { SHA384_Update(to_native_ptr(ptr), data, size); }
331
332
0
void do_get(SHA384Val::StatePtr ptr, u_char* digest) { SHA384_Final(digest, to_native_ptr(ptr)); }
333
334
0
std::string do_serialize(SHA384Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(SHA512_CTX)}; }
335
336
0
void do_unserialize(SHA384Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
337
338
0
void do_destroy(SHA384Val::StatePtr ptr) { delete to_native_ptr(ptr); }
339
340
// -- SHA512
341
342
0
auto* to_native_ptr(SHA512Val::StatePtr ptr) { return reinterpret_cast<SHA512_CTX*>(ptr); }
343
344
0
void do_init(SHA512Val::StatePtr& ptr) {
345
0
    auto ctx = new SHA512_CTX;
346
0
    SHA512_Init(ctx);
347
0
    ptr = reinterpret_cast<SHA512Val::StatePtr>(ctx);
348
0
}
349
350
0
void do_clone(SHA512Val::StatePtr out, SHA512Val::StatePtr in) { *to_native_ptr(out) = *to_native_ptr(in); }
351
352
0
void do_feed(SHA512Val::StatePtr ptr, const void* data, size_t size) { SHA512_Update(to_native_ptr(ptr), data, size); }
353
354
0
void do_get(SHA512Val::StatePtr ptr, u_char* digest) { SHA512_Final(digest, to_native_ptr(ptr)); }
355
356
0
std::string do_serialize(SHA512Val::StatePtr ptr) { return {reinterpret_cast<const char*>(ptr), sizeof(SHA512_CTX)}; }
357
358
0
void do_unserialize(SHA512Val::StatePtr ptr, const char* bytes, size_t len) { memcpy(ptr, bytes, len); }
359
360
0
void do_destroy(SHA512Val::StatePtr ptr) { delete to_native_ptr(ptr); }
361
362
} // namespace
363
364
2.06M
MD5Val::MD5Val() : HashVal(md5_type) {}
365
366
2.06M
MD5Val::~MD5Val() { do_destroy(ctx); }
367
368
38.1k
void HashVal::digest_one(detail::HashDigestState* h, const Val* v) {
369
38.1k
    if ( v->GetType()->Tag() == TYPE_STRING ) {
370
38.1k
        const String* str = v->AsString();
371
38.1k
        detail::hash_update(h, str->Bytes(), str->Len());
372
38.1k
    }
373
0
    else {
374
0
        ODesc d(DESC_BINARY);
375
0
        v->Describe(&d);
376
0
        detail::hash_update(h, d.Bytes(), d.Size());
377
0
    }
378
38.1k
}
379
380
38.1k
void HashVal::digest_one(detail::HashDigestState* h, const ValPtr& v) { digest_one(h, v.get()); }
381
382
0
ValPtr MD5Val::DoClone(CloneState* state) {
383
0
    auto out = make_intrusive<MD5Val>();
384
385
0
    if ( IsValid() ) {
386
0
        if ( ! out->Init() )
387
0
            return nullptr;
388
0
        do_clone(out->ctx, ctx);
389
0
    }
390
391
0
    return state->NewClone(this, std::move(out));
392
0
}
393
394
2.06M
bool MD5Val::DoInit() {
395
2.06M
    assert(! IsValid());
396
2.06M
    do_init(ctx);
397
2.06M
    return true;
398
2.06M
}
399
400
32.4M
bool MD5Val::DoFeed(const void* data, size_t size) {
401
32.4M
    if ( ! IsValid() )
402
0
        return false;
403
32.4M
    do_feed(ctx, data, size);
404
32.4M
    return true;
405
32.4M
}
406
407
1.32M
StringValPtr MD5Val::DoGet() {
408
1.32M
    if ( ! IsValid() )
409
0
        return val_mgr->EmptyString();
410
411
1.32M
    u_char digest[ZEEK_MD5_DIGEST_LENGTH];
412
1.32M
    do_get(ctx, digest);
413
1.32M
    return make_intrusive<StringVal>(detail::md5_digest_print(digest));
414
1.32M
}
415
416
IMPLEMENT_OPAQUE_VALUE(MD5Val)
417
418
0
std::optional<BrokerData> MD5Val::DoSerializeData() const {
419
0
    BrokerListBuilder builder;
420
421
0
    if ( ! IsValid() ) {
422
0
        builder.Add(false);
423
0
        return std::move(builder).Build();
424
0
    }
425
426
0
    builder.Reserve(2);
427
0
    builder.Add(true);
428
0
    builder.Add(do_serialize(ctx));
429
0
    return std::move(builder).Build();
430
0
}
431
432
0
bool MD5Val::DoUnserializeData(BrokerDataView data) {
433
0
    if ( ! data.IsList() )
434
0
        return false;
435
0
    auto d = data.ToList();
436
437
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
438
0
        return false;
439
440
0
    if ( ! d[0].ToBool() ) {
441
0
        assert(! IsValid()); // default set by ctor
442
0
        return true;
443
0
    }
444
445
0
    if ( d.Size() != 2 || ! d[1].IsString() )
446
0
        return false;
447
448
0
    auto s = d[1].ToString();
449
450
0
    if ( s.size() != MD5VAL_STATE_SIZE )
451
0
        return false;
452
453
0
    Init();
454
0
    do_unserialize(ctx, s.data(), s.size());
455
0
    return true;
456
0
}
457
458
2.06M
SHA1Val::SHA1Val() : HashVal(sha1_type) {}
459
460
2.06M
SHA1Val::~SHA1Val() { do_destroy(ctx); }
461
462
0
ValPtr SHA1Val::DoClone(CloneState* state) {
463
0
    auto out = make_intrusive<SHA1Val>();
464
465
0
    if ( IsValid() ) {
466
0
        if ( ! out->Init() )
467
0
            return nullptr;
468
469
0
        do_clone(out->ctx, ctx);
470
0
    }
471
472
0
    return state->NewClone(this, std::move(out));
473
0
}
474
475
2.06M
bool SHA1Val::DoInit() {
476
2.06M
    assert(! IsValid());
477
2.06M
    do_init(ctx);
478
2.06M
    return true;
479
2.06M
}
480
481
32.4M
bool SHA1Val::DoFeed(const void* data, size_t size) {
482
32.4M
    if ( ! IsValid() )
483
0
        return false;
484
485
32.4M
    do_feed(ctx, data, size);
486
32.4M
    return true;
487
32.4M
}
488
489
1.32M
StringValPtr SHA1Val::DoGet() {
490
1.32M
    if ( ! IsValid() )
491
0
        return val_mgr->EmptyString();
492
493
1.32M
    u_char digest[SHA_DIGEST_LENGTH];
494
1.32M
    do_get(ctx, digest);
495
1.32M
    return make_intrusive<StringVal>(detail::sha1_digest_print(digest));
496
1.32M
}
497
498
IMPLEMENT_OPAQUE_VALUE(SHA1Val)
499
500
0
std::optional<BrokerData> SHA1Val::DoSerializeData() const {
501
0
    BrokerListBuilder builder;
502
503
0
    if ( ! IsValid() ) {
504
0
        builder.Add(false);
505
0
        return std::move(builder).Build();
506
0
    }
507
508
0
    builder.Reserve(2);
509
0
    builder.Add(true);
510
0
    builder.Add(do_serialize(ctx));
511
0
    return std::move(builder).Build();
512
0
}
513
514
0
bool SHA1Val::DoUnserializeData(BrokerDataView data) {
515
0
    if ( ! data.IsList() )
516
0
        return false;
517
518
0
    auto d = data.ToList();
519
520
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
521
0
        return false;
522
523
0
    if ( ! d[0].ToBool() ) {
524
0
        assert(! IsValid()); // default set by ctor
525
0
        return true;
526
0
    }
527
528
0
    if ( d.Size() != 2 || ! d[1].IsString() )
529
0
        return false;
530
531
0
    auto s = d[1].ToString();
532
533
0
    if ( s.size() != SHA1VAL_STATE_SIZE )
534
0
        return false;
535
536
0
    Init();
537
0
    do_unserialize(ctx, s.data(), s.size());
538
0
    return true;
539
0
}
540
541
0
SHA224Val::SHA224Val() : HashVal(sha224_type) {}
542
543
0
SHA224Val::~SHA224Val() {
544
0
    if ( ctx != nullptr )
545
0
        do_destroy(ctx);
546
0
}
547
548
0
ValPtr SHA224Val::DoClone(CloneState* state) {
549
0
    auto out = make_intrusive<SHA224Val>();
550
551
0
    if ( IsValid() ) {
552
0
        if ( ! out->Init() )
553
0
            return nullptr;
554
555
0
        do_clone(out->ctx, ctx);
556
0
    }
557
558
0
    return state->NewClone(this, std::move(out));
559
0
}
560
561
0
bool SHA224Val::DoInit() {
562
0
    assert(! IsValid());
563
0
    do_init(ctx);
564
0
    return true;
565
0
}
566
567
0
bool SHA224Val::DoFeed(const void* data, size_t size) {
568
0
    if ( ! IsValid() )
569
0
        return false;
570
571
0
    do_feed(ctx, data, size);
572
0
    return true;
573
0
}
574
575
0
StringValPtr SHA224Val::DoGet() {
576
0
    if ( ! IsValid() )
577
0
        return val_mgr->EmptyString();
578
579
0
    u_char digest[SHA224_DIGEST_LENGTH];
580
0
    do_get(ctx, digest);
581
0
    return make_intrusive<StringVal>(detail::sha224_digest_print(digest));
582
0
}
583
584
IMPLEMENT_OPAQUE_VALUE(SHA224Val)
585
586
0
std::optional<BrokerData> SHA224Val::DoSerializeData() const {
587
0
    BrokerListBuilder builder;
588
589
0
    if ( ! IsValid() ) {
590
0
        builder.Add(false);
591
0
        return std::move(builder).Build();
592
0
    }
593
594
0
    builder.Add(true);
595
0
    builder.Add(do_serialize(ctx));
596
0
    return std::move(builder).Build();
597
0
}
598
599
0
bool SHA224Val::DoUnserializeData(BrokerDataView data) {
600
0
    if ( ! data.IsList() )
601
0
        return false;
602
603
0
    auto d = data.ToList();
604
605
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
606
0
        return false;
607
608
0
    if ( ! d[0].ToBool() ) {
609
0
        assert(! IsValid()); // default set by ctor
610
0
        return true;
611
0
    }
612
613
0
    if ( d.Size() != 2 || ! d[1].IsString() )
614
0
        return false;
615
616
0
    auto s = d[1].ToString();
617
618
0
    if ( s.size() != SHA224VAL_STATE_SIZE )
619
0
        return false;
620
621
0
    Init();
622
0
    do_unserialize(ctx, s.data(), s.size());
623
0
    return true;
624
0
}
625
626
2.06M
SHA256Val::SHA256Val() : HashVal(sha256_type) {}
627
628
2.06M
SHA256Val::~SHA256Val() {
629
2.06M
    if ( ctx != nullptr )
630
2.06M
        do_destroy(ctx);
631
2.06M
}
632
633
0
ValPtr SHA256Val::DoClone(CloneState* state) {
634
0
    auto out = make_intrusive<SHA256Val>();
635
636
0
    if ( IsValid() ) {
637
0
        if ( ! out->Init() )
638
0
            return nullptr;
639
640
0
        do_clone(out->ctx, ctx);
641
0
    }
642
643
0
    return state->NewClone(this, std::move(out));
644
0
}
645
646
2.06M
bool SHA256Val::DoInit() {
647
2.06M
    assert(! IsValid());
648
2.06M
    do_init(ctx);
649
2.06M
    return true;
650
2.06M
}
651
652
32.4M
bool SHA256Val::DoFeed(const void* data, size_t size) {
653
32.4M
    if ( ! IsValid() )
654
0
        return false;
655
656
32.4M
    do_feed(ctx, data, size);
657
32.4M
    return true;
658
32.4M
}
659
660
1.32M
StringValPtr SHA256Val::DoGet() {
661
1.32M
    if ( ! IsValid() )
662
0
        return val_mgr->EmptyString();
663
664
1.32M
    u_char digest[SHA256_DIGEST_LENGTH];
665
1.32M
    do_get(ctx, digest);
666
1.32M
    return make_intrusive<StringVal>(detail::sha256_digest_print(digest));
667
1.32M
}
668
669
IMPLEMENT_OPAQUE_VALUE(SHA256Val)
670
671
0
std::optional<BrokerData> SHA256Val::DoSerializeData() const {
672
0
    BrokerListBuilder builder;
673
674
0
    if ( ! IsValid() ) {
675
0
        builder.Add(false);
676
0
        return std::move(builder).Build();
677
0
    }
678
679
0
    builder.Add(true);
680
0
    builder.Add(do_serialize(ctx));
681
0
    return std::move(builder).Build();
682
0
}
683
684
0
bool SHA256Val::DoUnserializeData(BrokerDataView data) {
685
0
    if ( ! data.IsList() )
686
0
        return false;
687
688
0
    auto d = data.ToList();
689
690
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
691
0
        return false;
692
693
0
    if ( ! d[0].ToBool() ) {
694
0
        assert(! IsValid()); // default set by ctor
695
0
        return true;
696
0
    }
697
698
0
    if ( d.Size() != 2 || ! d[1].IsString() )
699
0
        return false;
700
701
0
    auto s = d[1].ToString();
702
703
0
    if ( s.size() != SHA256VAL_STATE_SIZE )
704
0
        return false;
705
706
0
    Init();
707
0
    do_unserialize(ctx, s.data(), s.size());
708
0
    return true;
709
0
}
710
711
0
SHA384Val::SHA384Val() : HashVal(sha384_type) {}
712
713
0
SHA384Val::~SHA384Val() {
714
0
    if ( ctx != nullptr )
715
0
        do_destroy(ctx);
716
0
}
717
718
0
ValPtr SHA384Val::DoClone(CloneState* state) {
719
0
    auto out = make_intrusive<SHA384Val>();
720
721
0
    if ( IsValid() ) {
722
0
        if ( ! out->Init() )
723
0
            return nullptr;
724
725
0
        do_clone(out->ctx, ctx);
726
0
    }
727
728
0
    return state->NewClone(this, std::move(out));
729
0
}
730
731
0
bool SHA384Val::DoInit() {
732
0
    assert(! IsValid());
733
0
    do_init(ctx);
734
0
    return true;
735
0
}
736
737
0
bool SHA384Val::DoFeed(const void* data, size_t size) {
738
0
    if ( ! IsValid() )
739
0
        return false;
740
741
0
    do_feed(ctx, data, size);
742
0
    return true;
743
0
}
744
745
0
StringValPtr SHA384Val::DoGet() {
746
0
    if ( ! IsValid() )
747
0
        return val_mgr->EmptyString();
748
749
0
    u_char digest[SHA384_DIGEST_LENGTH];
750
0
    do_get(ctx, digest);
751
0
    return make_intrusive<StringVal>(detail::sha384_digest_print(digest));
752
0
}
753
754
IMPLEMENT_OPAQUE_VALUE(SHA384Val)
755
756
0
std::optional<BrokerData> SHA384Val::DoSerializeData() const {
757
0
    BrokerListBuilder builder;
758
759
0
    if ( ! IsValid() ) {
760
0
        builder.Add(false);
761
0
        return std::move(builder).Build();
762
0
    }
763
764
0
    builder.Add(true);
765
0
    builder.Add(do_serialize(ctx));
766
0
    return std::move(builder).Build();
767
0
}
768
769
0
bool SHA384Val::DoUnserializeData(BrokerDataView data) {
770
0
    if ( ! data.IsList() )
771
0
        return false;
772
773
0
    auto d = data.ToList();
774
775
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
776
0
        return false;
777
778
0
    if ( ! d[0].ToBool() ) {
779
0
        assert(! IsValid()); // default set by ctor
780
0
        return true;
781
0
    }
782
783
0
    if ( d.Size() != 2 || ! d[1].IsString() )
784
0
        return false;
785
786
0
    auto s = d[1].ToString();
787
788
0
    if ( s.size() != SHA384VAL_STATE_SIZE )
789
0
        return false;
790
791
0
    Init();
792
0
    do_unserialize(ctx, s.data(), s.size());
793
0
    return true;
794
0
}
795
796
0
SHA512Val::SHA512Val() : HashVal(sha512_type) {}
797
798
0
SHA512Val::~SHA512Val() {
799
0
    if ( ctx != nullptr )
800
0
        do_destroy(ctx);
801
0
}
802
803
0
ValPtr SHA512Val::DoClone(CloneState* state) {
804
0
    auto out = make_intrusive<SHA512Val>();
805
806
0
    if ( IsValid() ) {
807
0
        if ( ! out->Init() )
808
0
            return nullptr;
809
810
0
        do_clone(out->ctx, ctx);
811
0
    }
812
813
0
    return state->NewClone(this, std::move(out));
814
0
}
815
816
0
bool SHA512Val::DoInit() {
817
0
    assert(! IsValid());
818
0
    do_init(ctx);
819
0
    return true;
820
0
}
821
822
0
bool SHA512Val::DoFeed(const void* data, size_t size) {
823
0
    if ( ! IsValid() )
824
0
        return false;
825
826
0
    do_feed(ctx, data, size);
827
0
    return true;
828
0
}
829
830
0
StringValPtr SHA512Val::DoGet() {
831
0
    if ( ! IsValid() )
832
0
        return val_mgr->EmptyString();
833
834
0
    u_char digest[SHA512_DIGEST_LENGTH];
835
0
    do_get(ctx, digest);
836
0
    return make_intrusive<StringVal>(detail::sha512_digest_print(digest));
837
0
}
838
839
IMPLEMENT_OPAQUE_VALUE(SHA512Val)
840
841
0
std::optional<BrokerData> SHA512Val::DoSerializeData() const {
842
0
    BrokerListBuilder builder;
843
844
0
    if ( ! IsValid() ) {
845
0
        builder.Add(false);
846
0
        return std::move(builder).Build();
847
0
    }
848
849
0
    builder.Add(true);
850
0
    builder.Add(do_serialize(ctx));
851
0
    return std::move(builder).Build();
852
0
}
853
854
0
bool SHA512Val::DoUnserializeData(BrokerDataView data) {
855
0
    if ( ! data.IsList() )
856
0
        return false;
857
858
0
    auto d = data.ToList();
859
860
0
    if ( d.IsEmpty() || ! d[0].IsBool() )
861
0
        return false;
862
863
0
    if ( ! d[0].ToBool() ) {
864
0
        assert(! IsValid()); // default set by ctor
865
0
        return true;
866
0
    }
867
868
0
    if ( d.Size() != 2 || ! d[1].IsString() )
869
0
        return false;
870
871
0
    auto s = d[1].ToString();
872
873
0
    if ( s.size() != SHA512VAL_STATE_SIZE )
874
0
        return false;
875
876
0
    Init();
877
0
    do_unserialize(ctx, s.data(), s.size());
878
0
    return true;
879
0
}
880
881
0
EntropyVal::EntropyVal() : OpaqueVal(entropy_type) {}
882
883
0
bool EntropyVal::Feed(const void* data, size_t size) {
884
0
    state.add(data, size);
885
0
    return true;
886
0
}
887
888
0
bool EntropyVal::Get(double* r_ent, double* r_chisq, double* r_mean, double* r_montepicalc, double* r_scc) {
889
0
    state.end(r_ent, r_chisq, r_mean, r_montepicalc, r_scc);
890
0
    return true;
891
0
}
892
893
IMPLEMENT_OPAQUE_VALUE(EntropyVal)
894
895
0
std::optional<BrokerData> EntropyVal::DoSerializeData() const {
896
0
    constexpr size_t numMembers = 14; // RandTest has 14 non-array members.
897
898
0
    BrokerListBuilder builder;
899
0
    builder.Reserve(numMembers + std::size(state.ccount) + std::size(state.monte));
900
901
0
    builder.Add(static_cast<uint64_t>(state.totalc));
902
0
    builder.Add(static_cast<uint64_t>(state.mp));
903
0
    builder.Add(static_cast<uint64_t>(state.sccfirst));
904
0
    builder.Add(static_cast<uint64_t>(state.inmont));
905
0
    builder.Add(static_cast<uint64_t>(state.mcount));
906
0
    builder.Add(static_cast<uint64_t>(state.cexp));
907
0
    builder.Add(static_cast<uint64_t>(state.montex));
908
0
    builder.Add(static_cast<uint64_t>(state.montey));
909
0
    builder.Add(static_cast<uint64_t>(state.montepi));
910
0
    builder.Add(static_cast<uint64_t>(state.sccu0));
911
0
    builder.Add(static_cast<uint64_t>(state.scclast));
912
0
    builder.Add(static_cast<uint64_t>(state.scct1));
913
0
    builder.Add(static_cast<uint64_t>(state.scct2));
914
0
    builder.Add(static_cast<uint64_t>(state.scct3));
915
916
0
    for ( auto bin : state.ccount )
917
0
        builder.Add(static_cast<uint64_t>(bin));
918
919
0
    for ( auto val : state.monte )
920
0
        builder.Add(static_cast<uint64_t>(val));
921
922
0
    return std::move(builder).Build();
923
0
}
924
925
0
bool EntropyVal::DoUnserializeData(BrokerDataView data) {
926
0
    if ( ! data.IsList() )
927
0
        return false;
928
929
0
    auto index = size_t{0};
930
931
0
    auto d = data.ToList();
932
933
0
    if ( ! get_vector_idx_if_count(d, index++, &state.totalc) )
934
0
        return false;
935
0
    if ( ! get_vector_idx_if_count(d, index++, &state.mp) )
936
0
        return false;
937
0
    if ( ! get_vector_idx_if_count(d, index++, &state.sccfirst) )
938
0
        return false;
939
0
    if ( ! get_vector_idx_if_count(d, index++, &state.inmont) )
940
0
        return false;
941
0
    if ( ! get_vector_idx_if_count(d, index++, &state.mcount) )
942
0
        return false;
943
0
    if ( ! get_vector_idx_if_count(d, index++, &state.cexp) )
944
0
        return false;
945
0
    if ( ! get_vector_idx_if_count(d, index++, &state.montex) )
946
0
        return false;
947
0
    if ( ! get_vector_idx_if_count(d, index++, &state.montey) )
948
0
        return false;
949
0
    if ( ! get_vector_idx_if_count(d, index++, &state.montepi) )
950
0
        return false;
951
0
    if ( ! get_vector_idx_if_count(d, index++, &state.sccu0) )
952
0
        return false;
953
0
    if ( ! get_vector_idx_if_count(d, index++, &state.scclast) )
954
0
        return false;
955
0
    if ( ! get_vector_idx_if_count(d, index++, &state.scct1) )
956
0
        return false;
957
0
    if ( ! get_vector_idx_if_count(d, index++, &state.scct2) )
958
0
        return false;
959
0
    if ( ! get_vector_idx_if_count(d, index++, &state.scct3) )
960
0
        return false;
961
962
0
    for ( auto& bin : state.ccount ) {
963
0
        if ( ! get_vector_idx_if_count(d, index++, &bin) )
964
0
            return false;
965
0
    }
966
967
0
    for ( auto& val : state.monte ) {
968
0
        if ( ! get_vector_idx_if_count(d, index++, &val) )
969
0
            return false;
970
0
    }
971
972
0
    return true;
973
0
}
974
975
0
BloomFilterVal::BloomFilterVal() : OpaqueVal(bloomfilter_type) {
976
0
    hash = nullptr;
977
0
    bloom_filter = nullptr;
978
0
}
979
980
0
BloomFilterVal::BloomFilterVal(probabilistic::BloomFilter* bf) : OpaqueVal(bloomfilter_type) {
981
0
    hash = nullptr;
982
0
    bloom_filter = bf;
983
0
}
984
985
0
ValPtr BloomFilterVal::DoClone(CloneState* state) {
986
0
    if ( bloom_filter ) {
987
0
        auto bf = make_intrusive<BloomFilterVal>(bloom_filter->Clone());
988
0
        assert(type);
989
0
        if ( ! bf->Typify(type) )
990
0
            reporter->InternalError("Failed to typify new bloom_filter clone, clone already had valid type");
991
992
0
        return state->NewClone(this, std::move(bf));
993
0
    }
994
995
0
    return state->NewClone(this, make_intrusive<BloomFilterVal>());
996
0
}
997
998
0
bool BloomFilterVal::Typify(TypePtr arg_type) {
999
0
    if ( type )
1000
0
        return false;
1001
1002
0
    type = std::move(arg_type);
1003
1004
0
    auto tl = make_intrusive<TypeList>(type);
1005
0
    tl->Append(type);
1006
0
    hash = new detail::CompositeHash(std::move(tl));
1007
1008
0
    return true;
1009
0
}
1010
1011
0
void BloomFilterVal::Add(const Val* val) {
1012
0
    auto key = hash->MakeHashKey(*val, true);
1013
0
    bloom_filter->Add(key.get());
1014
0
}
1015
1016
0
bool BloomFilterVal::Decrement(const Val* val) {
1017
0
    auto key = hash->MakeHashKey(*val, true);
1018
0
    return bloom_filter->Decrement(key.get());
1019
0
}
1020
1021
0
size_t BloomFilterVal::Count(const Val* val) const {
1022
0
    auto key = hash->MakeHashKey(*val, true);
1023
0
    size_t cnt = bloom_filter->Count(key.get());
1024
0
    return cnt;
1025
0
}
1026
1027
0
void BloomFilterVal::Clear() { bloom_filter->Clear(); }
1028
1029
0
bool BloomFilterVal::Empty() const { return bloom_filter->Empty(); }
1030
1031
0
std::string BloomFilterVal::InternalState() const { return bloom_filter->InternalState(); }
1032
1033
0
BloomFilterValPtr BloomFilterVal::Merge(const BloomFilterVal* x, const BloomFilterVal* y) {
1034
0
    if ( x->Type() && // any one 0 is ok here
1035
0
         y->Type() && ! same_type(x->Type(), y->Type()) ) {
1036
0
        reporter->Error("cannot merge Bloom filters with different types");
1037
0
        return nullptr;
1038
0
    }
1039
1040
0
    auto final_type = x->Type() ? x->Type() : y->Type();
1041
1042
0
    if ( typeid(*x->bloom_filter) != typeid(*y->bloom_filter) ) {
1043
0
        reporter->Error("cannot merge different Bloom filter types");
1044
0
        return nullptr;
1045
0
    }
1046
1047
0
    probabilistic::BloomFilter* copy = x->bloom_filter->Clone();
1048
1049
0
    if ( ! copy->Merge(y->bloom_filter) ) {
1050
0
        delete copy;
1051
0
        reporter->Error("failed to merge Bloom filter");
1052
0
        return nullptr;
1053
0
    }
1054
1055
0
    auto merged = make_intrusive<BloomFilterVal>(copy);
1056
1057
0
    if ( final_type && ! merged->Typify(final_type) ) {
1058
0
        reporter->Error("failed to set type on merged Bloom filter");
1059
0
        return nullptr;
1060
0
    }
1061
1062
0
    return merged;
1063
0
}
1064
1065
0
BloomFilterValPtr BloomFilterVal::Intersect(const BloomFilterVal* x, const BloomFilterVal* y) {
1066
0
    if ( x->Type() && // any one 0 is ok here
1067
0
         y->Type() && ! same_type(x->Type(), y->Type()) ) {
1068
0
        reporter->Error("cannot merge Bloom filters with different types");
1069
0
        return nullptr;
1070
0
    }
1071
1072
0
    if ( typeid(*x->bloom_filter) != typeid(*y->bloom_filter) ) {
1073
0
        reporter->Error("cannot intersect different Bloom filter types");
1074
0
        return nullptr;
1075
0
    }
1076
1077
0
    auto intersected_bf = x->bloom_filter->Intersect(y->bloom_filter);
1078
1079
0
    if ( ! intersected_bf ) {
1080
0
        reporter->Error("failed to intersect Bloom filter");
1081
0
        return nullptr;
1082
0
    }
1083
1084
0
    auto final_type = x->Type() ? x->Type() : y->Type();
1085
1086
0
    auto intersected = make_intrusive<BloomFilterVal>(intersected_bf);
1087
1088
0
    if ( final_type && ! intersected->Typify(final_type) ) {
1089
0
        reporter->Error("Failed to set type on intersected bloom filter");
1090
0
        return nullptr;
1091
0
    }
1092
1093
0
    return intersected;
1094
0
}
1095
1096
0
BloomFilterVal::~BloomFilterVal() {
1097
0
    delete hash;
1098
0
    delete bloom_filter;
1099
0
}
1100
1101
IMPLEMENT_OPAQUE_VALUE(BloomFilterVal)
1102
1103
0
std::optional<BrokerData> BloomFilterVal::DoSerializeData() const {
1104
0
    BrokerListBuilder builder;
1105
1106
0
    if ( type ) {
1107
0
        auto t = SerializeType(type);
1108
0
        if ( ! t )
1109
0
            return std::nullopt;
1110
1111
0
        builder.Add(std::move(*t));
1112
0
    }
1113
0
    else
1114
0
        builder.AddNil();
1115
1116
0
    auto bf = bloom_filter->SerializeData();
1117
0
    if ( ! bf )
1118
0
        return std::nullopt;
1119
1120
0
    builder.Add(std::move(*bf));
1121
0
    return std::move(builder).Build();
1122
0
}
1123
1124
0
bool BloomFilterVal::DoUnserializeData(BrokerDataView data) {
1125
0
    if ( ! data.IsList() )
1126
0
        return false;
1127
1128
0
    auto v = data.ToList();
1129
1130
0
    if ( v.Size() != 2 )
1131
0
        return false;
1132
1133
0
    if ( ! v[0].IsNil() ) {
1134
0
        auto t = UnserializeType(v[0]);
1135
1136
0
        if ( ! (t && Typify(std::move(t))) )
1137
0
            return false;
1138
0
    }
1139
1140
0
    auto bf = probabilistic::BloomFilter::UnserializeData(v[1]);
1141
0
    if ( ! bf )
1142
0
        return false;
1143
1144
0
    bloom_filter = bf.release();
1145
0
    return true;
1146
0
}
1147
1148
0
CardinalityVal::CardinalityVal() : OpaqueVal(cardinality_type) {
1149
0
    c = nullptr;
1150
0
    hash = nullptr;
1151
0
}
1152
1153
0
CardinalityVal::CardinalityVal(probabilistic::detail::CardinalityCounter* arg_c) : OpaqueVal(cardinality_type) {
1154
0
    c = arg_c;
1155
0
    hash = nullptr;
1156
0
}
1157
1158
0
CardinalityVal::~CardinalityVal() {
1159
0
    delete c;
1160
0
    delete hash;
1161
0
}
1162
1163
0
ValPtr CardinalityVal::DoClone(CloneState* state) {
1164
0
    return state->NewClone(this, make_intrusive<CardinalityVal>(new probabilistic::detail::CardinalityCounter(*c)));
1165
0
}
1166
1167
0
bool CardinalityVal::Typify(TypePtr arg_type) {
1168
0
    if ( type )
1169
0
        return false;
1170
1171
0
    type = std::move(arg_type);
1172
1173
0
    auto tl = make_intrusive<TypeList>(type);
1174
0
    tl->Append(type);
1175
0
    hash = new detail::CompositeHash(std::move(tl));
1176
1177
0
    return true;
1178
0
}
1179
1180
0
void CardinalityVal::Add(const Val* val) {
1181
0
    auto key = hash->MakeHashKey(*val, true);
1182
0
    c->AddElement(key->Hash());
1183
0
}
1184
1185
IMPLEMENT_OPAQUE_VALUE(CardinalityVal)
1186
1187
0
std::optional<BrokerData> CardinalityVal::DoSerializeData() const {
1188
0
    BrokerListBuilder builder;
1189
0
    builder.Reserve(2);
1190
1191
0
    if ( type ) {
1192
0
        auto t = SerializeType(type);
1193
0
        if ( ! t )
1194
0
            return std::nullopt;
1195
1196
0
        builder.Add(std::move(*t));
1197
0
    }
1198
0
    else
1199
0
        builder.AddNil();
1200
1201
0
    auto cs = c->Serialize();
1202
0
    if ( ! cs )
1203
0
        return std::nullopt;
1204
1205
0
    builder.Add(std::move(*cs));
1206
0
    return std::move(builder).Build();
1207
0
}
1208
1209
0
bool CardinalityVal::DoUnserializeData(BrokerDataView data) {
1210
0
    if ( ! data.IsList() )
1211
0
        return false;
1212
1213
0
    auto v = data.ToList();
1214
1215
0
    if ( v.Size() != 2 )
1216
0
        return false;
1217
1218
0
    if ( ! v[0].IsNil() ) {
1219
0
        auto t = UnserializeType(v[0]);
1220
1221
0
        if ( ! (t && Typify(std::move(t))) )
1222
0
            return false;
1223
0
    }
1224
1225
0
    auto cu = probabilistic::detail::CardinalityCounter::Unserialize(v[1]);
1226
0
    if ( ! cu )
1227
0
        return false;
1228
1229
0
    c = cu.release();
1230
0
    return true;
1231
0
}
1232
1233
0
ParaglobVal::ParaglobVal(std::unique_ptr<paraglob::Paraglob> p) : OpaqueVal(paraglob_type) {
1234
0
    this->internal_paraglob = std::move(p);
1235
0
}
1236
1237
0
VectorValPtr ParaglobVal::Get(StringVal*& pattern) {
1238
0
    auto rval = make_intrusive<VectorVal>(id::string_vec);
1239
0
    std::string string_pattern(reinterpret_cast<const char*>(pattern->Bytes()), pattern->Len());
1240
1241
0
    std::vector<std::string> matches = this->internal_paraglob->get(string_pattern);
1242
0
    for ( size_t i = 0; i < matches.size(); i++ )
1243
0
        rval->Assign(i, make_intrusive<StringVal>(matches.at(i)));
1244
1245
0
    return rval;
1246
0
}
1247
1248
0
bool ParaglobVal::operator==(const ParaglobVal& other) const {
1249
0
    return *(this->internal_paraglob) == *(other.internal_paraglob);
1250
0
}
1251
1252
IMPLEMENT_OPAQUE_VALUE(ParaglobVal)
1253
1254
0
std::optional<BrokerData> ParaglobVal::DoSerializeData() const {
1255
0
    std::unique_ptr<std::vector<uint8_t>> iv = this->internal_paraglob->serialize();
1256
0
    BrokerListBuilder builder;
1257
0
    builder.Reserve(iv->size());
1258
0
    for ( uint8_t a : *iv )
1259
0
        builder.AddCount(a);
1260
0
    return std::move(builder).Build();
1261
0
}
1262
1263
0
bool ParaglobVal::DoUnserializeData(BrokerDataView data) {
1264
0
    if ( ! data.IsList() )
1265
0
        return false;
1266
1267
0
    auto d = data.ToList();
1268
1269
0
    auto iv = std::make_unique<std::vector<uint8_t>>();
1270
0
    iv->resize(d.Size());
1271
1272
0
    for ( size_t index = 0; index < d.Size(); ++index ) {
1273
0
        if ( ! get_vector_idx_if_count(d, index, iv->data() + index) )
1274
0
            return false;
1275
0
    }
1276
1277
0
    try {
1278
0
        this->internal_paraglob = std::make_unique<paraglob::Paraglob>(std::move(iv));
1279
0
    } catch ( const paraglob::underflow_error& e ) {
1280
0
        reporter->Error("Paraglob underflow error -> %s", e.what());
1281
0
        return false;
1282
0
    } catch ( const paraglob::overflow_error& e ) {
1283
0
        reporter->Error("Paraglob overflow error -> %s", e.what());
1284
0
        return false;
1285
0
    }
1286
1287
0
    return true;
1288
0
}
1289
1290
0
ValPtr ParaglobVal::DoClone(CloneState* state) {
1291
0
    try {
1292
0
        return make_intrusive<ParaglobVal>(std::make_unique<paraglob::Paraglob>(this->internal_paraglob->serialize()));
1293
0
    } catch ( const paraglob::underflow_error& e ) {
1294
0
        reporter->Error("Paraglob underflow error while cloning -> %s", e.what());
1295
0
        return nullptr;
1296
0
    } catch ( const paraglob::overflow_error& e ) {
1297
0
        reporter->Error("Paraglob overflow error while cloning -> %s", e.what());
1298
0
        return nullptr;
1299
0
    }
1300
0
}
1301
1302
} // namespace zeek