• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 22550902417

01 Mar 2026 07:32PM UTC coverage: 68.401% (-5.3%) from 73.687%
22550902417

Pull #14922

github

web-flow
github-actions: bump actions/upload-artifact from 6.0.0 to 7.0.0

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6.0.0 to 7.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #14922: github-actions: bump actions/upload-artifact from 6.0.0 to 7.0.0

218243 of 319063 relevant lines covered (68.4%)

3284926.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.22
/src/detect-reference.c
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 Breno Silva <breno.silva@gmail.com>
22
 * \author Anoop Saldanha <anoopsaldanha@gmail.com>
23
 *
24
 * Implements the reference keyword support
25
 */
26

27
#include "suricata-common.h"
28
#include "suricata.h"
29
#include "detect.h"
30
#include "detect-parse.h"
31
#include "detect-engine.h"
32
#include "detect-engine-mpm.h"
33

34
#include "decode.h"
35
#include "flow-var.h"
36
#include "decode-events.h"
37
#include "stream-tcp.h"
38

39
#include "util-reference-config.h"
40
#include "detect-reference.h"
41

42
#include "util-unittest.h"
43
#include "util-byte.h"
44
#include "util-debug.h"
45

46
/* Breakout key and scheme (optional) and domain/path (mandatory) */
47
#define PARSE_REGEX                                                                                \
48
    "^\\s*([A-Za-z0-9]+)\\s*,\"?\\s*\"?\\s*([a-zA-Z]+:\\/\\/)?([a-zA-Z0-9\\-_\\.\\/"               \
37✔
49
    "\\?\\=]+)\"?\\s*\"?"
37✔
50

51
static DetectParseRegex parse_regex;
52

53
#ifdef UNITTESTS
54
static void ReferenceRegisterTests(void);
55
#endif
56
static int DetectReferenceSetup(DetectEngineCtx *, Signature *s, const char *str);
57

58
/**
59
 * \brief Registration function for the reference: keyword
60
 */
61
void DetectReferenceRegister(void)
62
{
37✔
63
    sigmatch_table[DETECT_REFERENCE].name = "reference";
37✔
64
    sigmatch_table[DETECT_REFERENCE].desc = "direct to places where information about the rule can be found";
37✔
65
    sigmatch_table[DETECT_REFERENCE].url = "/rules/meta.html#reference";
37✔
66
    sigmatch_table[DETECT_REFERENCE].Setup = DetectReferenceSetup;
37✔
67
#ifdef UNITTESTS
3✔
68
    sigmatch_table[DETECT_REFERENCE].RegisterTests = ReferenceRegisterTests;
3✔
69
#endif
3✔
70
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
37✔
71
}
37✔
72

73
/**
74
 *  \brief Free a Reference object
75
 */
76
void DetectReferenceFree(DetectReference *ref)
77
{
38,322✔
78
    SCEnter();
38,322✔
79

80
    if (ref->key)
38,322✔
81
        SCFree(ref->key);
38,312✔
82

83
    if (ref->reference != NULL) {
38,322✔
84
        SCFree(ref->reference);
38,322✔
85
    }
38,322✔
86
    SCFree(ref);
38,322✔
87

88
    SCReturn;
38,322✔
89
}
38,322✔
90

91
/**
92
 * \internal
93
 * \brief This function is used to parse reference options passed via reference: keyword
94
 *
95
 * \param rawstr Pointer to the user provided reference options.
96
 *
97
 * \retval ref  Pointer to signature reference on success.
98
 * \retval NULL On failure.
99
 */
100
static DetectReference *DetectReferenceParse(const char *rawstr, DetectEngineCtx *de_ctx)
101
{
38,322✔
102
    SCEnter();
38,322✔
103

104
    int res = 0;
38,322✔
105
    size_t pcre2len;
38,322✔
106
    char key[REFERENCE_SYSTEM_NAME_MAX] = "";
38,322✔
107
    char scheme[REFERENCE_SYSTEM_NAME_MAX] = "";
38,322✔
108
    char uri[REFERENCE_CONTENT_NAME_MAX] = "";
38,322✔
109

110
    pcre2_match_data *match = NULL;
38,322✔
111
    int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
38,322✔
112
    if (ret != 4) {
38,322✔
113
        SCLogError("Unable to parse \"reference\" "
×
114
                   "keyword argument - \"%s\".   Invalid argument.",
×
115
                rawstr);
×
116
        if (match) {
×
117
            pcre2_match_data_free(match);
×
118
        }
×
119
        return NULL;
×
120
    }
×
121

122
    DetectReference *ref = SCCalloc(1, sizeof(DetectReference));
38,322✔
123
    if (unlikely(ref == NULL)) {
38,322✔
124
        pcre2_match_data_free(match);
×
125
        return NULL;
×
126
    }
×
127

128
    /* Position 1 = key (mandatory) */
129
    pcre2len = sizeof(key);
38,322✔
130
    res = pcre2_substring_copy_bynumber(match, 1, (PCRE2_UCHAR8 *)key, &pcre2len);
38,322✔
131
    if (res < 0) {
38,322✔
132
        SCLogError("pcre2_substring_copy_bynumber key failed");
×
133
        goto error;
×
134
    }
×
135

136
    /* Position 2 = scheme (optional) */
137
    pcre2len = sizeof(scheme);
38,322✔
138
    (void)pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)scheme, &pcre2len);
38,322✔
139

140
    /* Position 3 = domain-path (mandatory) */
141
    pcre2len = sizeof(uri);
38,322✔
142
    res = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)uri, &pcre2len);
38,322✔
143
    if (res < 0) {
38,322✔
144
        SCLogError("pcre2_substring_copy_bynumber domain-path failed");
×
145
        goto error;
×
146
    }
×
147

148
    size_t ref_len = strlen(uri);
38,322✔
149
    /* no key, reference -- return an error */
150
    if (strlen(key) == 0 || ref_len == 0)
38,322✔
151
        goto error;
×
152

153
    if (strlen(scheme)) {
38,322✔
154
        SCLogConfig("scheme value %s overrides key %s", scheme, key);
×
155
        ref->key = SCStrdup(scheme);
×
156
        /* already bound checked to be REFERENCE_SYSTEM_NAME_MAX or less */
157
        ref->key_len = (uint16_t)strlen(scheme);
×
158
    } else {
38,322✔
159

160
        SCRConfReference *lookup_ref_conf = SCRConfGetReference(key, de_ctx);
38,322✔
161
        if (lookup_ref_conf != NULL) {
38,322✔
162
            ref->key = SCStrdup(lookup_ref_conf->url);
38,312✔
163
            /* already bound checked to be REFERENCE_SYSTEM_NAME_MAX or less */
164
            ref->key_len = (uint16_t)strlen(ref->key);
38,312✔
165
        } else {
38,312✔
166
            if (SigMatchStrictEnabled(DETECT_REFERENCE)) {
10✔
167
                SCLogError("unknown reference key \"%s\"", key);
×
168
                goto error;
×
169
            }
×
170

171
            SCLogWarning("unknown reference key \"%s\"", key);
10✔
172

173
            char str[2048];
10✔
174
            snprintf(str, sizeof(str), "config reference: %s undefined\n", key);
10✔
175

176
            if (SCRConfAddReference(de_ctx, str) < 0)
10✔
177
                goto error;
×
178
            lookup_ref_conf = SCRConfGetReference(key, de_ctx);
10✔
179
            if (lookup_ref_conf == NULL)
10✔
180
                goto error;
×
181
        }
10✔
182
    }
38,322✔
183

184
    /* make a copy so we can free pcre's substring */
185
    ref->reference = SCStrdup(uri);
38,322✔
186
    if (ref->reference == NULL) {
38,322✔
187
        SCLogError("strdup failed: %s", strerror(errno));
×
188
        goto error;
×
189
    }
×
190

191
    /* already bound checked to be REFERENCE_CONTENT_NAME_MAX or less */
192
    ref->reference_len = (uint16_t)ref_len;
38,322✔
193

194
    pcre2_match_data_free(match);
38,322✔
195
    /* free the substrings */
196
    SCReturnPtr(ref, "Reference");
38,322✔
197

198
error:
×
199
    if (match) {
×
200
        pcre2_match_data_free(match);
×
201
    }
×
202
    DetectReferenceFree(ref);
×
203
    SCReturnPtr(NULL, "Reference");
×
204
}
38,322✔
205

206
/**
207
 * \internal
208
 * \brief Used to add the parsed reference into the current signature.
209
 *
210
 * \param de_ctx Pointer to the Detection Engine Context.
211
 * \param s      Pointer to the Current Signature.
212
 * \param m      Pointer to the Current SigMatch.
213
 * \param rawstr Pointer to the user provided reference options.
214
 *
215
 * \retval  0 On Success.
216
 * \retval -1 On Failure.
217
 */
218
static int DetectReferenceSetup(DetectEngineCtx *de_ctx, Signature *s,
219
                                const char *rawstr)
220
{
38,322✔
221
    SCEnter();
38,322✔
222

223
    DetectReference *sig_refs = NULL;
38,322✔
224

225
    DetectReference *ref = DetectReferenceParse(rawstr, de_ctx);
38,322✔
226
    if (ref == NULL)
38,322✔
227
        SCReturnInt(-1);
×
228

229
    SCLogDebug("ref %s %s", ref->key, ref->reference);
38,322✔
230

231
    if (s->references == NULL)  {
38,322✔
232
        s->references = ref;
27,197✔
233
    } else {
27,197✔
234
        sig_refs = s->references;
11,125✔
235
        while (sig_refs->next != NULL) {
14,639✔
236
            sig_refs = sig_refs->next;
3,514✔
237
        }
3,514✔
238
        sig_refs->next = ref;
11,125✔
239
        ref->next = NULL;
11,125✔
240
    }
11,125✔
241

242
    SCReturnInt(0);
38,322✔
243
}
38,322✔
244

245
/***************************************Unittests******************************/
246

247
#ifdef UNITTESTS
248

249
/**
250
 * \test one valid reference.
251
 *
252
 *  \retval 1 on success.
253
 *  \retval 0 on failure.
254
 */
255
static int DetectReferenceParseTest01(void)
256
{
1✔
257
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
258
    FAIL_IF_NULL(de_ctx);
1✔
259
    de_ctx->flags |= DE_QUIET;
1✔
260

261
    SCRConfDeInitContext(de_ctx);
1✔
262
    FILE *fd = SCRConfGenerateValidDummyReferenceConfigFD01();
1✔
263
    FAIL_IF_NULL(fd);
1✔
264
    SCRConfLoadReferenceConfigFile(de_ctx, fd);
1✔
265

266
    Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
1✔
267
            "(msg:\"One reference\"; reference:one,001-2010; sid:2;)");
1✔
268
    FAIL_IF_NULL(s);
1✔
269
    FAIL_IF_NULL(s->references);
1✔
270

271
    DetectReference *ref = s->references;
1✔
272
    FAIL_IF (strcmp(ref->key, "http://www.one.com") != 0);
1✔
273
    FAIL_IF (strcmp(ref->reference, "001-2010") != 0);
1✔
274

275
    DetectEngineCtxFree(de_ctx);
1✔
276
    PASS;
1✔
277
}
1✔
278

279
/**
280
 * \test for two valid references.
281
 *
282
 *  \retval 1 on success.
283
 *  \retval 0 on failure.
284
 */
285
static int DetectReferenceParseTest02(void)
286
{
1✔
287
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
288
    FAIL_IF_NULL(de_ctx);
1✔
289
    de_ctx->flags |= DE_QUIET;
1✔
290

291
    SCRConfDeInitContext(de_ctx);
1✔
292
    FILE *fd = SCRConfGenerateValidDummyReferenceConfigFD01();
1✔
293
    FAIL_IF_NULL(fd);
1✔
294
    SCRConfLoadReferenceConfigFile(de_ctx, fd);
1✔
295

296
    Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
1✔
297
                                   "(msg:\"Two references\"; "
1✔
298
                                   "reference:one,openinfosecdoundation.txt; "
1✔
299
                                   "reference:two,001-2010; sid:2;)");
1✔
300
    FAIL_IF_NULL(s);
1✔
301
    FAIL_IF_NULL(s->references);
1✔
302
    FAIL_IF_NULL(s->references->next);
1✔
303

304
    DetectReference *ref = s->references;
1✔
305
    FAIL_IF (strcmp(ref->key, "http://www.one.com") != 0);
1✔
306
    FAIL_IF (strcmp(ref->reference, "openinfosecdoundation.txt") != 0);
1✔
307

308
    ref = s->references->next;
1✔
309
    FAIL_IF (strcmp(ref->key, "http://www.two.com") != 0);
1✔
310
    FAIL_IF (strcmp(ref->reference, "001-2010") != 0);
1✔
311

312
    DetectEngineCtxFree(de_ctx);
1✔
313
    PASS;
1✔
314
}
1✔
315

316
/**
317
 * \test parsing: invalid reference.
318
 *
319
 *  \retval 1 on success.
320
 *  \retval 0 on failure.
321
 */
322
static int DetectReferenceParseTest03(void)
323
{
1✔
324
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
325
    FAIL_IF_NULL(de_ctx);
1✔
326
    de_ctx->flags |= DE_QUIET;
1✔
327

328
    SCRConfDeInitContext(de_ctx);
1✔
329
    FILE *fd = SCRConfGenerateValidDummyReferenceConfigFD01();
1✔
330
    FAIL_IF_NULL(fd);
1✔
331
    SCRConfLoadReferenceConfigFile(de_ctx, fd);
1✔
332

333
    Signature *s = DetectEngineAppendSig(de_ctx, "alert icmp any any -> any any "
1✔
334
                                   "(msg:\"invalid ref\"; "
1✔
335
                                   "reference:unknownkey,001-2010; sid:2;)");
1✔
336
    FAIL_IF_NULL(s);
1✔
337
    DetectEngineCtxFree(de_ctx);
1✔
338
    PASS;
1✔
339
}
1✔
340

341
static void ReferenceRegisterTests(void)
342
{
1✔
343
    UtRegisterTest("DetectReferenceParseTest01", DetectReferenceParseTest01);
1✔
344
    UtRegisterTest("DetectReferenceParseTest02", DetectReferenceParseTest02);
1✔
345
    UtRegisterTest("DetectReferenceParseTest03", DetectReferenceParseTest03);
1✔
346
}
1✔
347
#endif /* UNITTESTS */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc