Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-engine-siggroup.c
Line
Count
Source
1
/* Copyright (C) 2007-2021 Open Information Security Foundation
2
 *
3
 * You can copy, redistribute or modify this Program under the terms of
4
 * the GNU General Public License version 2 as published by the Free
5
 * Software Foundation.
6
 *
7
 * This program is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 * GNU General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU General Public License
13
 * version 2 along with this program; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15
 * 02110-1301, USA.
16
 */
17
18
/**
19
 * \file
20
 *
21
 * \author Victor Julien <victor@inliniac.net>
22
 *
23
 * Signature grouping part of the detection engine.
24
 */
25
26
#include "suricata-common.h"
27
#include "decode.h"
28
29
#include "flow-var.h"
30
31
#include "app-layer-protos.h"
32
33
#include "detect.h"
34
#include "detect-parse.h"
35
#include "detect-engine.h"
36
#include "detect-engine-build.h"
37
#include "detect-engine-address.h"
38
#include "detect-engine-mpm.h"
39
#include "detect-engine-siggroup.h"
40
#include "detect-engine-prefilter.h"
41
42
#include "detect-content.h"
43
#include "detect-uricontent.h"
44
#include "detect-tcp-flags.h"
45
46
#include "util-hash.h"
47
#include "util-hashlist.h"
48
49
#include "util-error.h"
50
#include "util-debug.h"
51
#include "util-validate.h"
52
#include "util-cidr.h"
53
#include "util-unittest.h"
54
#include "util-unittest-helper.h"
55
#include "util-memcmp.h"
56
57
/* prototypes */
58
int SigGroupHeadClearSigs(SigGroupHead *);
59
60
void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid)
61
10.6M
{
62
10.6M
    if (sghid->match_array != NULL) {
63
226k
        SCFree(sghid->match_array);
64
226k
        sghid->match_array = NULL;
65
226k
    }
66
10.6M
    if (sghid->sig_array != NULL) {
67
10.6M
        SCFreeAligned(sghid->sig_array);
68
10.6M
        sghid->sig_array = NULL;
69
10.6M
    }
70
10.6M
    if (sghid->app_mpms != NULL) {
71
225k
        SCFree(sghid->app_mpms);
72
225k
    }
73
10.6M
    if (sghid->pkt_mpms != NULL) {
74
225k
        SCFree(sghid->pkt_mpms);
75
225k
    }
76
10.6M
    if (sghid->frame_mpms != NULL) {
77
225k
        SCFree(sghid->frame_mpms);
78
225k
    }
79
80
10.6M
    PrefilterFreeEnginesList(sghid->tx_engines);
81
10.6M
    PrefilterFreeEnginesList(sghid->pkt_engines);
82
10.6M
    PrefilterFreeEnginesList(sghid->payload_engines);
83
10.6M
    PrefilterFreeEnginesList(sghid->frame_engines);
84
85
10.6M
    SCFree(sghid);
86
10.6M
}
87
88
static SigGroupHeadInitData *SigGroupHeadInitDataAlloc(uint32_t size)
89
10.6M
{
90
10.6M
    SigGroupHeadInitData *sghid = SCMalloc(sizeof(SigGroupHeadInitData));
91
10.6M
    if (unlikely(sghid == NULL))
92
0
        return NULL;
93
94
10.6M
    memset(sghid, 0x00, sizeof(SigGroupHeadInitData));
95
96
    /* initialize the signature bitarray */
97
10.6M
    size = sghid->sig_size = size + 16 - (size % 16);
98
10.6M
    void *ptr = SCMallocAligned(sghid->sig_size, 16);
99
10.6M
    if (ptr == NULL)
100
0
        goto error;
101
10.6M
    memset(ptr, 0, size);
102
10.6M
    sghid->sig_array = ptr;
103
104
10.6M
    memset(sghid->sig_array, 0, sghid->sig_size);
105
106
10.6M
    return sghid;
107
0
error:
108
0
    SigGroupHeadInitDataFree(sghid);
109
0
    return NULL;
110
10.6M
}
111
112
void SigGroupHeadStore(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
113
224k
{
114
224k
    void *ptmp;
115
    //printf("de_ctx->sgh_array_cnt %u, de_ctx->sgh_array_size %u, de_ctx->sgh_array %p\n", de_ctx->sgh_array_cnt, de_ctx->sgh_array_size, de_ctx->sgh_array);
116
224k
    if (de_ctx->sgh_array_cnt < de_ctx->sgh_array_size) {
117
173k
        de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
118
173k
    } else {
119
51.0k
        int increase = 16;
120
51.0k
        ptmp = SCRealloc(de_ctx->sgh_array,
121
51.0k
                         sizeof(SigGroupHead *) * (increase + de_ctx->sgh_array_size));
122
51.0k
        if (ptmp == NULL) {
123
0
            SCFree(de_ctx->sgh_array);
124
0
            de_ctx->sgh_array = NULL;
125
0
            return;
126
0
        }
127
51.0k
        de_ctx->sgh_array = ptmp;
128
129
51.0k
        de_ctx->sgh_array_size += increase;
130
51.0k
        de_ctx->sgh_array[de_ctx->sgh_array_cnt] = sgh;
131
51.0k
    }
132
224k
    de_ctx->sgh_array_cnt++;
133
224k
}
134
135
/**
136
 * \brief Alloc a SigGroupHead and its signature bit_array.
137
 *
138
 * \param size Size of the sig_array that has to be created for this
139
 *             SigGroupHead.
140
 *
141
 * \retval sgh Pointer to the newly init SigGroupHead on success; or NULL in
142
 *             case of error.
143
 */
144
static SigGroupHead *SigGroupHeadAlloc(const DetectEngineCtx *de_ctx, uint32_t size)
145
10.6M
{
146
10.6M
    SigGroupHead *sgh = SCMalloc(sizeof(SigGroupHead));
147
10.6M
    if (unlikely(sgh == NULL))
148
0
        return NULL;
149
10.6M
    memset(sgh, 0, sizeof(SigGroupHead));
150
151
10.6M
    sgh->init = SigGroupHeadInitDataAlloc(size);
152
10.6M
    if (sgh->init == NULL)
153
0
        goto error;
154
155
10.6M
    return sgh;
156
157
0
error:
158
0
    SigGroupHeadFree(de_ctx, sgh);
159
0
    return NULL;
160
10.6M
}
161
162
/**
163
 * \brief Free a SigGroupHead and its members.
164
 *
165
 * \param sgh Pointer to the SigGroupHead that has to be freed.
166
 */
167
void SigGroupHeadFree(const DetectEngineCtx *de_ctx, SigGroupHead *sgh)
168
5.49M
{
169
5.49M
    if (sgh == NULL)
170
0
        return;
171
172
5.49M
    SCLogDebug("sgh %p", sgh);
173
174
5.49M
    if (sgh->non_pf_other_store_array != NULL) {
175
101k
        SCFree(sgh->non_pf_other_store_array);
176
101k
        sgh->non_pf_other_store_array = NULL;
177
101k
        sgh->non_pf_other_store_cnt = 0;
178
101k
    }
179
180
5.49M
    if (sgh->non_pf_syn_store_array != NULL) {
181
101k
        SCFree(sgh->non_pf_syn_store_array);
182
101k
        sgh->non_pf_syn_store_array = NULL;
183
101k
        sgh->non_pf_syn_store_cnt = 0;
184
101k
    }
185
186
5.49M
    if (sgh->init != NULL) {
187
5.37M
        SigGroupHeadInitDataFree(sgh->init);
188
5.37M
        sgh->init = NULL;
189
5.37M
    }
190
191
5.49M
    PrefilterCleanupRuleGroup(de_ctx, sgh);
192
5.49M
    SCFree(sgh);
193
194
5.49M
    return;
195
5.49M
}
196
197
/**
198
 * \brief The hash function to be the used by the hash table -
199
 *        DetectEngineCtx->sgh_hash_table.
200
 *
201
 * \param ht      Pointer to the hash table.
202
 * \param data    Pointer to the SigGroupHead.
203
 * \param datalen Not used in our case.
204
 *
205
 * \retval hash The generated hash value.
206
 */
207
static uint32_t SigGroupHeadHashFunc(HashListTable *ht, void *data, uint16_t datalen)
208
10.1M
{
209
10.1M
    SigGroupHead *sgh = (SigGroupHead *)data;
210
10.1M
    uint32_t hash = 0;
211
10.1M
    uint32_t b = 0;
212
213
10.1M
    SCLogDebug("hashing sgh %p", sgh);
214
215
173M
    for (b = 0; b < sgh->init->sig_size; b++)
216
163M
        hash += sgh->init->sig_array[b];
217
218
10.1M
    hash %= ht->array_size;
219
10.1M
    SCLogDebug("hash %"PRIu32" (sig_size %"PRIu32")", hash, sgh->init->sig_size);
220
10.1M
    return hash;
221
10.1M
}
222
223
/**
224
 * \brief The Compare function to be used by the SigGroupHead hash table -
225
 *        DetectEngineCtx->sgh_hash_table.
226
 *
227
 * \param data1 Pointer to the first SigGroupHead.
228
 * \param len1  Not used.
229
 * \param data2 Pointer to the second SigGroupHead.
230
 * \param len2  Not used.
231
 *
232
 * \retval 1 If the 2 SigGroupHeads sent as args match.
233
 * \retval 0 If the 2 SigGroupHeads sent as args do not match.
234
 */
235
static char SigGroupHeadCompareFunc(void *data1, uint16_t len1, void *data2,
236
                             uint16_t len2)
237
9.67M
{
238
9.67M
    SigGroupHead *sgh1 = (SigGroupHead *)data1;
239
9.67M
    SigGroupHead *sgh2 = (SigGroupHead *)data2;
240
241
9.67M
    if (data1 == NULL || data2 == NULL)
242
0
        return 0;
243
244
9.67M
    if (sgh1->init->sig_size != sgh2->init->sig_size)
245
0
        return 0;
246
247
9.67M
    if (SCMemcmp(sgh1->init->sig_array, sgh2->init->sig_array, sgh1->init->sig_size) != 0)
248
3.13k
        return 0;
249
250
9.67M
    return 1;
251
9.67M
}
252
253
/**
254
 * \brief Initializes the hash table in the detection engine context to hold the
255
 *        SigGroupHeads.
256
 *
257
 * \param de_ctx Pointer to the detection engine context.
258
 *
259
 * \retval  0 On success.
260
 * \retval -1 On failure.
261
 */
262
int SigGroupHeadHashInit(DetectEngineCtx *de_ctx)
263
736k
{
264
736k
    de_ctx->sgh_hash_table = HashListTableInit(4096, SigGroupHeadHashFunc,
265
736k
                                               SigGroupHeadCompareFunc, NULL);
266
736k
    if (de_ctx->sgh_hash_table == NULL)
267
0
        goto error;
268
269
736k
    return 0;
270
271
0
error:
272
0
    return -1;
273
736k
}
274
275
/**
276
 * \brief Adds a SigGroupHead to the detection engine context SigGroupHead
277
 *        hash table.
278
 *
279
 * \param de_ctx Pointer to the detection engine context.
280
 * \param sgh    Pointer to the SigGroupHead.
281
 *
282
 * \retval ret 0 on Successfully adding the SigGroupHead; -1 on failure.
283
 */
284
int SigGroupHeadHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
285
224k
{
286
224k
    int ret = HashListTableAdd(de_ctx->sgh_hash_table, (void *)sgh, 0);
287
288
224k
    return ret;
289
224k
}
290
291
int SigGroupHeadHashRemove(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
292
0
{
293
0
    return HashListTableRemove(de_ctx->sgh_hash_table, (void *)sgh, 0);
294
0
}
295
296
/**
297
 * \brief Used to lookup a SigGroupHead hash from the detection engine context
298
 *        SigGroupHead hash table.
299
 *
300
 * \param de_ctx Pointer to the detection engine context.
301
 * \param sgh    Pointer to the SigGroupHead.
302
 *
303
 * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
304
 *              found in the hash table; NULL on failure.
305
 */
306
SigGroupHead *SigGroupHeadHashLookup(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
307
9.89M
{
308
9.89M
    SCEnter();
309
310
9.89M
    SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_hash_table,
311
9.89M
                                             (void *)sgh, 0);
312
313
9.89M
    SCReturnPtr(rsgh, "SigGroupHead");
314
9.89M
}
315
316
/**
317
 * \brief Frees the hash table - DetectEngineCtx->sgh_hash_table, allocated by
318
 *        SigGroupHeadHashInit() function.
319
 *
320
 * \param de_ctx Pointer to the detection engine context.
321
 */
322
void SigGroupHeadHashFree(DetectEngineCtx *de_ctx)
323
443k
{
324
443k
    if (de_ctx->sgh_hash_table == NULL)
325
63.4k
        return;
326
327
380k
    HashListTableFree(de_ctx->sgh_hash_table);
328
380k
    de_ctx->sgh_hash_table = NULL;
329
330
380k
    return;
331
443k
}
332
333
/**
334
 * \brief Add a Signature to a SigGroupHead.
335
 *
336
 * \param de_ctx Pointer to the detection engine context.
337
 * \param sgh    Pointer to a SigGroupHead.  Can be NULL also.
338
 * \param s      Pointer to the Signature that has to be added to the
339
 *               SigGroupHead.
340
 *
341
 * \retval  0 On success.
342
 * \retval -1 On failure.
343
 */
344
int SigGroupHeadAppendSig(const DetectEngineCtx *de_ctx, SigGroupHead **sgh,
345
                          const Signature *s)
346
17.4M
{
347
17.4M
    if (de_ctx == NULL)
348
0
        return 0;
349
350
    /* see if we have a head already */
351
17.4M
    if (*sgh == NULL) {
352
5.08M
        *sgh = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
353
5.08M
        if (*sgh == NULL)
354
0
            goto error;
355
5.08M
    }
356
357
    /* enable the sig in the bitarray */
358
17.4M
    (*sgh)->init->sig_array[s->num / 8] |= 1 << (s->num % 8);
359
360
17.4M
    return 0;
361
362
0
error:
363
0
    return -1;
364
17.4M
}
365
366
/**
367
 * \brief Clears the bitarray holding the sids for this SigGroupHead.
368
 *
369
 * \param sgh Pointer to the SigGroupHead.
370
 *
371
 * \retval 0 Always.
372
 */
373
int SigGroupHeadClearSigs(SigGroupHead *sgh)
374
0
{
375
0
    if (sgh == NULL)
376
0
        return 0;
377
378
0
    if (sgh->init->sig_array != NULL)
379
0
        memset(sgh->init->sig_array, 0, sgh->init->sig_size);
380
381
0
    sgh->init->sig_cnt = 0;
382
383
0
    return 0;
384
0
}
385
386
#ifdef __SSE2__
387
#include <emmintrin.h>
388
static void MergeBitarrays(const uint8_t *src, uint8_t *dst, const uint32_t size)
389
1.12M
{
390
2.28M
#define BYTES 16
391
1.12M
    const uint8_t *srcptr = src;
392
1.12M
    uint8_t *dstptr = dst;
393
2.26M
    for (uint32_t i = 0; i < size; i += 16) {
394
1.14M
        __m128i s = _mm_load_si128((const __m128i *)srcptr);
395
1.14M
        __m128i d = _mm_load_si128((const __m128i *)dstptr);
396
1.14M
        d = _mm_or_si128(s, d);
397
1.14M
        _mm_store_si128((__m128i *)dstptr, d);
398
1.14M
        srcptr += BYTES;
399
1.14M
        dstptr += BYTES;
400
1.14M
    }
401
1.12M
}
402
#endif
403
404
/**
405
 * \brief Copies the bitarray holding the sids from the source SigGroupHead to
406
 *        the destination SigGroupHead.
407
 *
408
 * \param de_ctx Pointer to the detection engine context.
409
 * \param src    Pointer to the source SigGroupHead.
410
 * \param dst    Pointer to the destination SigGroupHead.
411
 *
412
 * \retval  0 On success.
413
 * \retval -1 On failure.
414
 */
415
int SigGroupHeadCopySigs(DetectEngineCtx *de_ctx, SigGroupHead *src, SigGroupHead **dst)
416
1.00M
{
417
1.00M
    if (src == NULL || de_ctx == NULL)
418
340k
        return 0;
419
420
666k
    if (*dst == NULL) {
421
404k
        *dst = SigGroupHeadAlloc(de_ctx, DetectEngineGetMaxSigId(de_ctx) / 8 + 1);
422
404k
        if (*dst == NULL)
423
0
            goto error;
424
404k
    }
425
666k
    DEBUG_VALIDATE_BUG_ON(src->init->sig_size != (*dst)->init->sig_size);
426
427
666k
#ifdef __SSE2__
428
666k
    MergeBitarrays(src->init->sig_array, (*dst)->init->sig_array, src->init->sig_size);
429
#else
430
    /* do the copy */
431
    for (uint32_t idx = 0; idx < src->init->sig_size; idx++)
432
        (*dst)->init->sig_array[idx] = (*dst)->init->sig_array[idx] | src->init->sig_array[idx];
433
#endif
434
666k
    if (src->init->whitelist)
435
113k
        (*dst)->init->whitelist = MAX((*dst)->init->whitelist, src->init->whitelist);
436
437
666k
    return 0;
438
439
0
error:
440
0
    return -1;
441
666k
}
442
443
#ifdef HAVE_POPCNT64
444
#include <x86intrin.h>
445
static uint32_t Popcnt(const uint8_t *array, const uint32_t size)
446
359k
{
447
    /* input needs to be a multiple of 8 for u64 casts to work */
448
359k
    DEBUG_VALIDATE_BUG_ON(size < 8);
449
359k
    DEBUG_VALIDATE_BUG_ON(size % 8);
450
451
359k
    uint32_t cnt = 0;
452
359k
    uint64_t *ptr = (uint64_t *)array;
453
1.08M
    for (uint64_t idx = 0; idx < size; idx += 8) {
454
725k
        cnt += _popcnt64(*ptr);
455
725k
        ptr++;
456
725k
    }
457
359k
    return cnt;
458
359k
}
459
#endif
460
461
/**
462
 * \brief Updates the SigGroupHead->sig_cnt with the total count of all the
463
 *        Signatures present in this SigGroupHead.
464
 *
465
 * \param sgh     Pointer to the SigGroupHead.
466
 * \param max_idx Maximum sid of the all the Signatures present in this
467
 *                SigGroupHead.
468
 */
469
void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
470
201k
{
471
201k
#ifdef HAVE_POPCNT64
472
201k
    sgh->init->sig_cnt = Popcnt(sgh->init->sig_array, sgh->init->sig_size);
473
#else
474
    uint32_t cnt = 0;
475
    for (uint32_t sig = 0; sig < max_idx + 1; sig++) {
476
        if (sgh->init->sig_array[sig / 8] & (1 << (sig % 8)))
477
            cnt++;
478
    }
479
    sgh->init->sig_cnt = cnt;
480
#endif
481
201k
    return;
482
201k
}
483
484
/**
485
 * \brief Finds if two Signature Group Heads are the same.
486
 *
487
 * \param sgha First SGH to be compared
488
 * \param sghb Secornd SGH to be compared
489
 *
490
 * \return true if they're a match, false otherwise
491
 */
492
bool SigGroupHeadEqual(const SigGroupHead *sgha, const SigGroupHead *sghb)
493
187k
{
494
187k
    if (sgha == NULL || sghb == NULL)
495
0
        return false;
496
497
187k
    if (sgha->init->sig_size != sghb->init->sig_size)
498
0
        return false;
499
500
187k
    if (SCMemcmp(sgha->init->sig_array, sghb->init->sig_array, sgha->init->sig_size) != 0)
501
61.7k
        return false;
502
503
126k
    return true;
504
187k
}
505
506
void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh,
507
                                      uint8_t ipproto, int dir)
508
204k
{
509
204k
    if (sgh && sgh->init) {
510
204k
        SCLogDebug("setting proto %u and dir %d on sgh %p", ipproto, dir, sgh);
511
204k
        sgh->init->protos[ipproto] = 1;
512
204k
        sgh->init->direction |= dir;
513
204k
    }
514
204k
}
515
516
/**
517
 * \brief Helper function used to print the list of sids for the Signatures
518
 *        present in this SigGroupHead.
519
 *
520
 * \param de_ctx Pointer to the detection engine context.
521
 * \param sgh    Pointer to the SigGroupHead.
522
 */
523
void SigGroupHeadPrintSigs(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
524
0
{
525
0
    SCEnter();
526
527
0
    if (sgh == NULL) {
528
0
        SCReturn;
529
0
    }
530
531
0
    uint32_t u;
532
533
0
    SCLogDebug("The Signatures present in this SigGroupHead are: ");
534
0
    for (u = 0; u < (sgh->init->sig_size * 8); u++) {
535
0
        if (sgh->init->sig_array[u / 8] & (1 << (u % 8))) {
536
0
            SCLogDebug("%" PRIu32, u);
537
0
            printf("s->num %"PRIu32" ", u);
538
0
        }
539
0
    }
540
541
0
    SCReturn;
542
0
}
543
544
/**
545
 * \brief Create an array with all the internal ids of the sigs that this
546
 *        sig group head will check for.
547
 *
548
 * \param de_ctx  Pointer to the detection engine context.
549
 * \param sgh     Pointer to the SigGroupHead.
550
 * \param max_idx The maximum value of the sid in the SigGroupHead arg.
551
 *
552
 * \retval  0 success
553
 * \retval -1 error
554
 */
555
int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
556
                                uint32_t max_idx)
557
119k
{
558
119k
    Signature *s = NULL;
559
119k
    uint32_t idx = 0;
560
119k
    uint32_t sig = 0;
561
562
119k
    if (sgh == NULL)
563
0
        return 0;
564
565
119k
    BUG_ON(sgh->init->match_array != NULL);
566
567
119k
    sgh->init->match_array = SCMalloc(sgh->init->sig_cnt * sizeof(Signature *));
568
119k
    if (sgh->init->match_array == NULL)
569
0
        return -1;
570
571
119k
    memset(sgh->init->match_array, 0, sgh->init->sig_cnt * sizeof(Signature *));
572
573
1.48M
    for (sig = 0; sig < max_idx + 1; sig++) {
574
1.36M
        if (!(sgh->init->sig_array[(sig / 8)] & (1 << (sig % 8))) )
575
615k
            continue;
576
577
749k
        s = de_ctx->sig_array[sig];
578
749k
        if (s == NULL)
579
0
            continue;
580
581
749k
        sgh->init->match_array[idx] = s;
582
749k
        idx++;
583
749k
    }
584
585
119k
    return 0;
586
119k
}
587
588
/**
589
 *  \brief Set the need magic flag in the sgh.
590
 *
591
 *  \param de_ctx detection engine ctx for the signatures
592
 *  \param sgh sig group head to set the flag in
593
 */
594
void SigGroupHeadSetFilemagicFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
595
119k
{
596
#ifdef HAVE_MAGIC
597
    Signature *s = NULL;
598
    uint32_t sig = 0;
599
600
    if (sgh == NULL)
601
        return;
602
603
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
604
        s = sgh->init->match_array[sig];
605
        if (s == NULL)
606
            continue;
607
608
        if (SignatureIsFilemagicInspecting(s)) {
609
            sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMAGIC;
610
            break;
611
        }
612
    }
613
#endif
614
119k
    return;
615
119k
}
616
617
/**
618
 *  \brief Set the need size flag in the sgh.
619
 *
620
 *  \param de_ctx detection engine ctx for the signatures
621
 *  \param sgh sig group head to set the flag in
622
 */
623
void SigGroupHeadSetFilesizeFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
624
119k
{
625
119k
    Signature *s = NULL;
626
119k
    uint32_t sig = 0;
627
628
119k
    if (sgh == NULL)
629
0
        return;
630
631
848k
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
632
729k
        s = sgh->init->match_array[sig];
633
729k
        if (s == NULL)
634
0
            continue;
635
636
729k
        if (SignatureIsFilesizeInspecting(s)) {
637
656
            sgh->flags |= SIG_GROUP_HEAD_HAVEFILESIZE;
638
656
            break;
639
656
        }
640
729k
    }
641
642
119k
    return;
643
119k
}
644
645
/**
646
 *  \brief Set the need hash flag in the sgh.
647
 *
648
 *  \param de_ctx detection engine ctx for the signatures
649
 *  \param sgh sig group head to set the flag in
650
 */
651
void SigGroupHeadSetFileHashFlag(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
652
119k
{
653
119k
    Signature *s = NULL;
654
119k
    uint32_t sig = 0;
655
656
119k
    if (sgh == NULL)
657
0
        return;
658
659
849k
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
660
730k
        s = sgh->init->match_array[sig];
661
730k
        if (s == NULL)
662
0
            continue;
663
664
730k
        if (SignatureIsFileMd5Inspecting(s)) {
665
0
            sgh->flags |= SIG_GROUP_HEAD_HAVEFILEMD5;
666
0
            SCLogDebug("sgh %p has filemd5", sgh);
667
0
            break;
668
0
        }
669
670
730k
        if (SignatureIsFileSha1Inspecting(s)) {
671
0
            sgh->flags |= SIG_GROUP_HEAD_HAVEFILESHA1;
672
0
            SCLogDebug("sgh %p has filesha1", sgh);
673
0
            break;
674
0
        }
675
676
730k
        if (SignatureIsFileSha256Inspecting(s)) {
677
0
            sgh->flags |= SIG_GROUP_HEAD_HAVEFILESHA256;
678
0
            SCLogDebug("sgh %p has filesha256", sgh);
679
0
            break;
680
0
        }
681
730k
    }
682
683
119k
    return;
684
119k
}
685
686
/**
687
 *  \brief Set the filestore_cnt in the sgh.
688
 *
689
 *  \param de_ctx detection engine ctx for the signatures
690
 *  \param sgh sig group head to set the counter in
691
 */
692
void SigGroupHeadSetFilestoreCount(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
693
119k
{
694
119k
    Signature *s = NULL;
695
119k
    uint32_t sig = 0;
696
697
119k
    if (sgh == NULL)
698
0
        return;
699
700
849k
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
701
730k
        s = sgh->init->match_array[sig];
702
730k
        if (s == NULL)
703
0
            continue;
704
705
730k
        if (SignatureIsFilestoring(s)) {
706
            // should be insured by caller that we do not overflow
707
29.5k
            DEBUG_VALIDATE_BUG_ON(sgh->filestore_cnt == UINT16_MAX);
708
29.5k
            sgh->filestore_cnt++;
709
29.5k
        }
710
730k
    }
711
712
119k
    return;
713
119k
}
714
715
/** \brief build an array of rule id's for sigs with no prefilter
716
 *  Also updated de_ctx::non_pf_store_cnt_max to track the highest cnt
717
 */
718
int SigGroupHeadBuildNonPrefilterArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
719
119k
{
720
119k
    Signature *s = NULL;
721
119k
    uint32_t sig = 0;
722
119k
    uint32_t non_pf = 0;
723
119k
    uint32_t non_pf_syn = 0;
724
725
119k
    if (sgh == NULL)
726
0
        return 0;
727
728
119k
    BUG_ON(sgh->non_pf_other_store_array != NULL);
729
730
869k
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
731
749k
        s = sgh->init->match_array[sig];
732
749k
        if (s == NULL)
733
0
            continue;
734
735
749k
        if (!(s->flags & SIG_FLAG_PREFILTER) || (s->flags & SIG_FLAG_MPM_NEG)) {
736
512k
            if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
737
511k
                non_pf++;
738
511k
            }
739
512k
            non_pf_syn++;
740
512k
        }
741
749k
    }
742
743
119k
    if (non_pf == 0 && non_pf_syn == 0) {
744
17.9k
        sgh->non_pf_other_store_array = NULL;
745
17.9k
        sgh->non_pf_syn_store_array = NULL;
746
17.9k
        return 0;
747
17.9k
    }
748
749
101k
    if (non_pf > 0) {
750
101k
        sgh->non_pf_other_store_array = SCMalloc(non_pf * sizeof(SignatureNonPrefilterStore));
751
101k
        BUG_ON(sgh->non_pf_other_store_array == NULL);
752
101k
        memset(sgh->non_pf_other_store_array, 0, non_pf * sizeof(SignatureNonPrefilterStore));
753
101k
    }
754
755
101k
    if (non_pf_syn > 0) {
756
101k
        sgh->non_pf_syn_store_array = SCMalloc(non_pf_syn * sizeof(SignatureNonPrefilterStore));
757
101k
        BUG_ON(sgh->non_pf_syn_store_array == NULL);
758
101k
        memset(sgh->non_pf_syn_store_array, 0, non_pf_syn * sizeof(SignatureNonPrefilterStore));
759
101k
    }
760
761
812k
    for (sig = 0; sig < sgh->init->sig_cnt; sig++) {
762
710k
        s = sgh->init->match_array[sig];
763
710k
        if (s == NULL)
764
0
            continue;
765
766
710k
        if (!(s->flags & SIG_FLAG_PREFILTER) || (s->flags & SIG_FLAG_MPM_NEG)) {
767
512k
            if (!(DetectFlagsSignatureNeedsSynPackets(s))) {
768
511k
                BUG_ON(sgh->non_pf_other_store_cnt >= non_pf);
769
511k
                BUG_ON(sgh->non_pf_other_store_array == NULL);
770
511k
                sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].id = s->num;
771
511k
                sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].mask = s->mask;
772
511k
                sgh->non_pf_other_store_array[sgh->non_pf_other_store_cnt].alproto = s->alproto;
773
511k
                sgh->non_pf_other_store_cnt++;
774
511k
            }
775
776
512k
            BUG_ON(sgh->non_pf_syn_store_cnt >= non_pf_syn);
777
512k
            BUG_ON(sgh->non_pf_syn_store_array == NULL);
778
512k
            sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].id = s->num;
779
512k
            sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].mask = s->mask;
780
512k
            sgh->non_pf_syn_store_array[sgh->non_pf_syn_store_cnt].alproto = s->alproto;
781
512k
            sgh->non_pf_syn_store_cnt++;
782
512k
        }
783
710k
    }
784
785
    /* track highest cnt for any sgh in our de_ctx */
786
101k
    uint32_t max = MAX(sgh->non_pf_other_store_cnt, sgh->non_pf_syn_store_cnt);
787
101k
    if (max > de_ctx->non_pf_store_cnt_max)
788
21.5k
        de_ctx->non_pf_store_cnt_max = max;
789
790
101k
    return 0;
791
101k
}
792
793
/**
794
 * \brief Check if a SigGroupHead contains a Signature, whose sid is sent as an
795
 *        argument.
796
 *
797
 * \param de_ctx Pointer to the detection engine context.
798
 * \param sgh    Pointer to the SigGroupHead that has to be checked for the
799
 *               presence of a Signature.
800
 * \param sid    The Signature id(sid) that has to be checked in the SigGroupHead.
801
 *
802
 * \retval 1 On successfully finding the sid in the SigGroupHead.
803
 * \retval 0 If the sid is not found in the SigGroupHead
804
 */
805
int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
806
                              uint32_t sid)
807
0
{
808
0
    SCEnter();
809
810
0
    uint32_t sig = 0;
811
0
    Signature *s = NULL;
812
0
    uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx);
813
814
0
    if (sgh == NULL) {
815
0
        SCReturnInt(0);
816
0
    }
817
818
0
    for (sig = 0; sig < max_sid; sig++) {
819
0
        if (sgh->init->sig_array == NULL) {
820
0
            SCReturnInt(0);
821
0
        }
822
823
        /* Check if the SigGroupHead has an entry for the sid */
824
0
        if ( !(sgh->init->sig_array[sig / 8] & (1 << (sig % 8))) )
825
0
            continue;
826
827
        /* If we have reached here, we have an entry for sid in the SigGroupHead.
828
         * Retrieve the Signature from the detection engine context */
829
0
        s = de_ctx->sig_array[sig];
830
0
        if (s == NULL)
831
0
            continue;
832
833
        /* If the retrieved Signature matches the sid arg, we have a match */
834
0
        if (s->id == sid) {
835
0
            SCReturnInt(1);
836
0
        }
837
0
    }
838
839
0
    SCReturnInt(0);
840
0
}
841
842
/*----------------------------------Unittests---------------------------------*/
843
844
#ifdef UNITTESTS
845
846
int SigAddressPrepareStage1(DetectEngineCtx *);
847
848
/**
849
 * \test Check if a SigGroupHead hash table is properly allocated and
850
 *       deallocated when calling SigGroupHeadHashInit() and
851
 *       SigGroupHeadHashFree() respectively.
852
 */
853
static int SigGroupHeadTest01(void)
854
{
855
    DetectEngineCtx de_ctx;
856
857
    SigGroupHeadHashInit(&de_ctx);
858
    FAIL_IF_NULL(de_ctx.sgh_hash_table);
859
860
    SigGroupHeadHashFree(&de_ctx);
861
    FAIL_IF_NOT_NULL(de_ctx.sgh_hash_table);
862
863
    PASS;
864
}
865
866
/**
867
 * \test Check if a SigGroupHeadAppendSig() correctly appends a sid to a
868
 *       SigGroupHead() and SigGroupHeadContainsSigId() correctly indicates
869
 *       the presence of a sid.
870
 */
871
static int SigGroupHeadTest02(void)
872
{
873
    SigGroupHead *sh = NULL;
874
875
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
876
    FAIL_IF_NULL(de_ctx);
877
878
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
879
                                                 "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
880
                                                 "content:\"test2\"; content:\"test3\"; sid:1;)");
881
    FAIL_IF_NULL(s);
882
883
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
884
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
885
                                      "content:\"test2\"; content:\"test3\"; sid:2;)");
886
    FAIL_IF_NULL(s);
887
888
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
889
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
890
                                      "content:\"test2\"; content:\"test3\"; sid:3;)");
891
    FAIL_IF_NULL(s);
892
893
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
894
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
895
                                      "content:\"test2\"; content:\"test3\"; sid:4;)");
896
    FAIL_IF_NULL(s);
897
898
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
899
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
900
                                      "content:\"test2\"; content:\"test3\"; sid:5;)");
901
    FAIL_IF_NULL(s);
902
903
    SigAddressPrepareStage1(de_ctx);
904
905
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
906
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
907
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
908
909
    SigGroupHeadSetSigCnt(sh, 4);
910
911
    FAIL_IF_NOT(sh->init->sig_cnt == 3);
912
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 1) == 1);
913
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
914
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 3) == 1);
915
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
916
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 5) == 1);
917
918
    SigGroupHeadFree(de_ctx, sh);
919
920
    DetectEngineCtxFree(de_ctx);
921
922
    PASS;
923
}
924
925
/**
926
 * \test Check if a SigGroupHeadAppendSig(), correctly appends a sid to a
927
 *       SigGroupHead() and SigGroupHeadContainsSigId(), correctly indicates
928
 *       the presence of a sid and SigGroupHeadClearSigs(), correctly clears
929
 *       the SigGroupHead->sig_array and SigGroupHead->sig_cnt.
930
 */
931
static int SigGroupHeadTest03(void)
932
{
933
    SigGroupHead *sh = NULL;
934
935
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
936
    FAIL_IF_NULL(de_ctx);
937
938
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
939
                                                 "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
940
                                                 "content:\"test2\"; content:\"test3\"; sid:1;)");
941
    FAIL_IF_NULL(s);
942
943
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
944
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
945
                                      "content:\"test2\"; content:\"test3\"; sid:2;)");
946
    FAIL_IF_NULL(s);
947
948
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
949
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
950
                                      "content:\"test2\"; content:\"test3\"; sid:3;)");
951
    FAIL_IF_NULL(s);
952
953
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
954
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
955
                                      "content:\"test2\"; content:\"test3\"; sid:4;)");
956
    FAIL_IF_NULL(s);
957
958
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
959
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
960
                                      "content:\"test2\"; content:\"test3\"; sid:5;)");
961
    FAIL_IF_NULL(s);
962
963
    SigAddressPrepareStage1(de_ctx);
964
965
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
966
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
967
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
968
969
    SigGroupHeadSetSigCnt(sh, 4);
970
971
    FAIL_IF_NOT(sh->init->sig_cnt == 3);
972
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 1) == 1);
973
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
974
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 3) == 1);
975
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
976
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 5) == 1);
977
978
    SigGroupHeadClearSigs(sh);
979
980
    FAIL_IF_NOT(sh->init->sig_cnt == 0);
981
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 1) == 0);
982
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 2) == 0);
983
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 3) == 0);
984
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 4) == 0);
985
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, sh, 5) == 0);
986
987
    SigGroupHeadFree(de_ctx, sh);
988
989
    DetectEngineCtxFree(de_ctx);
990
991
    PASS;
992
}
993
994
/**
995
 * \test Check if SigGroupHeadCopySigs(), correctly copies the sig_array from
996
 *       the source to the destination SigGroupHead.
997
 */
998
static int SigGroupHeadTest04(void)
999
{
1000
    SigGroupHead *src_sh = NULL;
1001
    SigGroupHead *dst_sh = NULL;
1002
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1003
1004
    FAIL_IF_NULL(de_ctx);
1005
1006
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1007
                                                 "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1008
                                                 "content:\"test2\"; content:\"test3\"; sid:1;)");
1009
    FAIL_IF_NULL(s);
1010
1011
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1012
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1013
                                      "content:\"test2\"; content:\"test3\"; sid:2;)");
1014
    FAIL_IF_NULL(s);
1015
1016
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1017
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1018
                                      "content:\"test2\"; content:\"test3\"; sid:3;)");
1019
    FAIL_IF_NULL(s);
1020
1021
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1022
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1023
                                      "content:\"test2\"; content:\"test3\"; sid:4;)");
1024
    FAIL_IF_NULL(s);
1025
1026
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1027
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1028
                                      "content:\"test2\"; content:\"test3\"; sid:5;)");
1029
    FAIL_IF_NULL(s);
1030
1031
    SigAddressPrepareStage1(de_ctx);
1032
1033
    SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list);
1034
    SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next);
1035
    SigGroupHeadAppendSig(de_ctx, &src_sh, de_ctx->sig_list->next->next->next->next);
1036
1037
    SigGroupHeadSetSigCnt(src_sh, 4);
1038
1039
    FAIL_IF_NOT(src_sh->init->sig_cnt == 3);
1040
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 1) == 1);
1041
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 2) == 0);
1042
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 3) == 1);
1043
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 4) == 0);
1044
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, src_sh, 5) == 1);
1045
1046
    SigGroupHeadCopySigs(de_ctx, src_sh, &dst_sh);
1047
1048
    SigGroupHeadSetSigCnt(dst_sh, 4);
1049
1050
    FAIL_IF_NOT(dst_sh->init->sig_cnt == 3);
1051
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 1) == 1);
1052
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 2) == 0);
1053
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 3) == 1);
1054
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 4) == 0);
1055
    FAIL_IF_NOT(SigGroupHeadContainsSigId(de_ctx, dst_sh, 5) == 1);
1056
1057
    SigGroupHeadFree(de_ctx, src_sh);
1058
    SigGroupHeadFree(de_ctx, dst_sh);
1059
1060
    DetectEngineCtxFree(de_ctx);
1061
1062
    PASS;
1063
}
1064
1065
/**
1066
 * \test Check if SigGroupHeadBuildMatchArray(), correctly updates the
1067
 *       match array with the sids.
1068
 */
1069
static int SigGroupHeadTest05(void)
1070
{
1071
    SigGroupHead *sh = NULL;
1072
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1073
1074
    FAIL_IF_NULL(de_ctx);
1075
1076
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1077
                                                 "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1078
                                                 "content:\"test2\"; content:\"test3\"; sid:1;)");
1079
    FAIL_IF_NULL(s);
1080
1081
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1082
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1083
                                      "content:\"test2\"; content:\"test3\"; sid:2;)");
1084
    FAIL_IF_NULL(s);
1085
1086
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1087
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1088
                                      "content:\"test2\"; content:\"test3\"; sid:3;)");
1089
    FAIL_IF_NULL(s);
1090
1091
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1092
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1093
                                      "content:\"test2\"; content:\"test3\"; sid:4;)");
1094
    FAIL_IF_NULL(s);
1095
1096
    s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
1097
                                      "(msg:\"SigGroupHead tests\"; content:\"test1\"; "
1098
                                      "content:\"test2\"; content:\"test3\"; sid:5;)");
1099
    FAIL_IF_NULL(s);
1100
1101
    SigAddressPrepareStage1(de_ctx);
1102
1103
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list);
1104
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next);
1105
    SigGroupHeadAppendSig(de_ctx, &sh, de_ctx->sig_list->next->next->next->next);
1106
1107
    SigGroupHeadSetSigCnt(sh, 4);
1108
    SigGroupHeadBuildMatchArray(de_ctx, sh, 4);
1109
1110
    /* matching an array to a queue structure (sig_list) constructed by SigInit()
1111
1112
    FAIL_IF_NOT(sh->init->match_array[0] == de_ctx->sig_list);
1113
    FAIL_IF_NOT(sh->init->match_array[1] == de_ctx->sig_list->next->next);
1114
    FAIL_IF_NOT(sh->init->match_array[2] == de_ctx->sig_list->next->next->next->next);
1115
    */
1116
1117
    // matching an array to a stack structure (sig_list) constructed by DetectEngineAppendSig()
1118
    FAIL_IF_NOT(sh->init->match_array[0] == de_ctx->sig_list->next->next->next->next);
1119
    FAIL_IF_NOT(sh->init->match_array[1] == de_ctx->sig_list->next->next);
1120
    FAIL_IF_NOT(sh->init->match_array[2] == de_ctx->sig_list);
1121
1122
    SigGroupHeadFree(de_ctx, sh);
1123
1124
    DetectEngineCtxFree(de_ctx);
1125
1126
    PASS;
1127
}
1128
1129
/**
1130
 * \test ICMP(?) sig grouping bug.
1131
 */
1132
static int SigGroupHeadTest06(void)
1133
{
1134
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1135
    DetectEngineThreadCtx *det_ctx = NULL;
1136
    ThreadVars th_v;
1137
1138
    memset(&th_v, 0, sizeof(ThreadVars));
1139
1140
    Packet *p = UTHBuildPacketSrcDst(NULL, 0, IPPROTO_ICMP, "192.168.1.1", "1.2.3.4");
1141
    FAIL_IF_NULL(p);
1142
1143
    p->icmpv4h->type = 5;
1144
    p->icmpv4h->code = 1;
1145
1146
    /* originally ip's were
1147
    p.src.addr_data32[0] = 0xe08102d3;
1148
    p.dst.addr_data32[0] = 0x3001a8c0;
1149
    */
1150
1151
    FAIL_IF_NULL(de_ctx);
1152
1153
    Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp 192.168.0.0/16 any -> any any "
1154
                                                 "(icode:>1; itype:11; sid:1; rev:1;)");
1155
    FAIL_IF_NULL(s);
1156
1157
    s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> 192.168.0.0/16 any "
1158
                                      "(icode:1; itype:5; sid:2; rev:1;)");
1159
    FAIL_IF_NULL(s);
1160
1161
    SigGroupBuild(de_ctx);
1162
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1163
1164
    AddressDebugPrint(&p->dst);
1165
1166
    const SigGroupHead *sgh = SigMatchSignaturesGetSgh(de_ctx, p);
1167
    FAIL_IF_NULL(sgh);
1168
1169
    DetectEngineCtxFree(de_ctx);
1170
    UTHFreePackets(&p, 1);
1171
1172
    PASS;
1173
}
1174
#endif
1175
1176
void SigGroupHeadRegisterTests(void)
1177
0
{
1178
#ifdef UNITTESTS
1179
    UtRegisterTest("SigGroupHeadTest01", SigGroupHeadTest01);
1180
    UtRegisterTest("SigGroupHeadTest02", SigGroupHeadTest02);
1181
    UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03);
1182
    UtRegisterTest("SigGroupHeadTest04", SigGroupHeadTest04);
1183
    UtRegisterTest("SigGroupHeadTest05", SigGroupHeadTest05);
1184
    UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06);
1185
#endif
1186
0
}