Coverage Report

Created: 2025-12-31 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-priority.c
Line
Count
Source
1
/* Copyright (C) 2007-2020 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
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23
 *
24
 * Implements the priority keyword
25
 */
26
27
#include "suricata-common.h"
28
#include "detect.h"
29
#include "detect-parse.h"
30
#include "detect-priority.h"
31
#include "detect-engine.h"
32
#include "detect-engine-mpm.h"
33
#include "util-error.h"
34
#include "util-debug.h"
35
#include "util-unittest.h"
36
37
73
#define PARSE_REGEX "^\\s*(\\d+|\"\\d+\")\\s*$"
38
39
static DetectParseRegex parse_regex;
40
41
static int DetectPrioritySetup (DetectEngineCtx *, Signature *, const char *);
42
#ifdef UNITTESTS
43
static void PriorityRegisterTests(void);
44
#endif
45
46
/**
47
 * \brief Registers the handler functions for the "priority" keyword
48
 */
49
void DetectPriorityRegister (void)
50
73
{
51
73
    sigmatch_table[DETECT_PRIORITY].name = "priority";
52
73
    sigmatch_table[DETECT_PRIORITY].desc = "rules with a higher priority will be examined first";
53
73
    sigmatch_table[DETECT_PRIORITY].url = "/rules/meta.html#priority";
54
73
    sigmatch_table[DETECT_PRIORITY].Setup = DetectPrioritySetup;
55
#ifdef UNITTESTS
56
    sigmatch_table[DETECT_PRIORITY].RegisterTests = PriorityRegisterTests;
57
#endif
58
73
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
59
73
}
60
61
static int DetectPrioritySetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
62
11.3k
{
63
11.3k
    char copy_str[128] = "";
64
11.3k
    size_t pcre2len;
65
66
11.3k
    pcre2_match_data *match = NULL;
67
11.3k
    int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
68
11.3k
    if (ret < 0) {
69
238
        SCLogError("Invalid Priority in Signature "
70
238
                   "- %s",
71
238
                rawstr);
72
238
        if (match)
73
238
            pcre2_match_data_free(match);
74
238
        return -1;
75
238
    }
76
77
11.0k
    pcre2len = sizeof(copy_str);
78
11.0k
    ret = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)copy_str, &pcre2len);
79
11.0k
    if (ret < 0) {
80
144
        SCLogError("pcre2_substring_copy_bynumber failed");
81
144
        pcre2_match_data_free(match);
82
144
        return -1;
83
144
    }
84
85
11.0k
    pcre2_match_data_free(match);
86
10.9k
    char *endptr = NULL;
87
10.9k
    long prio = strtol(copy_str, &endptr, 10);
88
10.9k
    if (endptr == NULL || *endptr != '\0') {
89
0
        SCLogError("Saw an invalid character as arg "
90
0
                   "to priority keyword");
91
0
        return -1;
92
0
    }
93
94
10.9k
    if (s->init_data->init_flags & SIG_FLAG_INIT_PRIO_EXPLICIT) {
95
3.87k
        SCLogWarning("duplicate priority "
96
3.87k
                     "keyword. Using highest priority in the rule");
97
3.87k
        s->prio = MIN(s->prio, prio);
98
7.05k
    } else {
99
7.05k
        s->prio = prio;
100
7.05k
        s->init_data->init_flags |= SIG_FLAG_INIT_PRIO_EXPLICIT;
101
7.05k
    }
102
10.9k
    return 0;
103
10.9k
}
104
105
/*------------------------------Unittests-------------------------------------*/
106
107
#ifdef UNITTESTS
108
109
static int DetectPriorityTest01(void)
110
{
111
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
112
    FAIL_IF_NULL(de_ctx);
113
114
    de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any "
115
                               "(msg:\"Priority test\"; priority:2; sid:1;)");
116
    FAIL_IF_NULL(de_ctx->sig_list);
117
118
    FAIL_IF_NOT(de_ctx->sig_list->prio == 2);
119
120
    DetectEngineCtxFree(de_ctx);
121
    PASS;
122
}
123
124
static int DetectPriorityTest02(void)
125
{
126
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
127
    FAIL_IF_NULL(de_ctx);
128
129
    Signature *sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
130
                  "(msg:\"Priority test\"; priority:1; sid:1;)");
131
    FAIL_IF_NULL(sig);
132
    FAIL_IF_NOT(sig->prio == 1);
133
134
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
135
                  "(msg:\"Priority test\"; priority:boo; sid:2;)");
136
    FAIL_IF_NOT_NULL(sig);
137
138
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
139
                  "(msg:\"Priority test\"; priority:10boo; sid:3;)");
140
    FAIL_IF_NOT_NULL(sig);
141
142
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
143
                  "(msg:\"Priority test\"; priority:b10oo; sid:4;)");
144
    FAIL_IF_NOT_NULL(sig);
145
146
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
147
                  "(msg:\"Priority test\"; priority:boo10; sid:5;)");
148
    FAIL_IF_NOT_NULL(sig);
149
150
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
151
                  "(msg:\"Priority test\"; priority:-1; sid:6;)");
152
    FAIL_IF_NOT_NULL(sig);
153
154
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
155
                  "(msg:\"Priority test\"; sid:7;)");
156
    FAIL_IF_NULL(sig);
157
    FAIL_IF_NOT(sig->prio == 3);
158
159
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
160
                  "(msg:\"Priority test\"; priority:5; priority:4; sid:8;)");
161
    FAIL_IF_NULL(sig);
162
    FAIL_IF_NOT(sig->prio == 4);
163
164
    sig = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any "
165
                  "(msg:\"Priority test\"; priority:5; priority:4; "
166
                  "priority:1; sid:9;)");
167
    FAIL_IF_NULL(sig);
168
    FAIL_IF_NOT(sig->prio == 1);
169
170
    DetectEngineCtxFree(de_ctx);
171
    PASS;
172
}
173
174
/**
175
 * \brief This function registers unit tests for Classification Config API.
176
 */
177
static void PriorityRegisterTests(void)
178
{
179
    UtRegisterTest("DetectPriorityTest01", DetectPriorityTest01);
180
    UtRegisterTest("DetectPriorityTest02", DetectPriorityTest02);
181
}
182
#endif /* UNITTESTS */