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

OISF / suricata / 23374838686

21 Mar 2026 07:29AM UTC coverage: 59.341% (-20.0%) from 79.315%
23374838686

Pull #15075

github

web-flow
Merge 90b4e834f into 6587e363a
Pull Request #15075: Stack 8001 v16.4

38 of 70 new or added lines in 10 files covered. (54.29%)

34165 existing lines in 563 files now uncovered.

119621 of 201584 relevant lines covered (59.34%)

650666.92 hits per line

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

93.38
/src/detect-base64-decode.c
1
/* Copyright (C) 2020-2024 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
#include "suricata-common.h"
19
#include "detect.h"
20
#include "detect-parse.h"
21
#include "detect-base64-decode.h"
22
#include "util-byte.h"
23
#include "util-print.h"
24
#include "detect-engine-build.h"
25
#include "rust.h"
26

27
/* Arbitrary maximum buffer size for decoded base64 data. */
28
#define BASE64_DECODE_MAX 65535
9,183✔
29

30
typedef struct DetectBase64Decode_ {
31
    uint16_t bytes;
32
    uint32_t offset;
33
    uint8_t relative;
34
} DetectBase64Decode;
35

36
static const char decode_pattern[] = "\\s*(bytes\\s+(\\d+),?)?"
37
    "\\s*(offset\\s+(\\d+),?)?"
38
    "\\s*(\\w+)?";
39

40
static DetectParseRegex decode_pcre;
41

42
static int DetectBase64DecodeSetup(DetectEngineCtx *, Signature *, const char *);
43
static void DetectBase64DecodeFree(DetectEngineCtx *, void *);
44
#ifdef UNITTESTS
45
static void DetectBase64DecodeRegisterTests(void);
46
#endif
47

48
void DetectBase64DecodeRegister(void)
49
{
3✔
50
    sigmatch_table[DETECT_BASE64_DECODE].name = "base64_decode";
3✔
51
    sigmatch_table[DETECT_BASE64_DECODE].desc =
3✔
52
        "Decodes base64 encoded data.";
3✔
53
    sigmatch_table[DETECT_BASE64_DECODE].url =
3✔
54
        "/rules/base64-keywords.html#base64-decode";
3✔
55
    sigmatch_table[DETECT_BASE64_DECODE].Setup = DetectBase64DecodeSetup;
3✔
56
    sigmatch_table[DETECT_BASE64_DECODE].Free = DetectBase64DecodeFree;
3✔
57
#ifdef UNITTESTS
58
    sigmatch_table[DETECT_BASE64_DECODE].RegisterTests =
59
        DetectBase64DecodeRegisterTests;
60
#endif
61
    sigmatch_table[DETECT_BASE64_DECODE].flags |= SIGMATCH_OPTIONAL_OPT;
3✔
62

63
    DetectSetupParseRegexes(decode_pattern, &decode_pcre);
3✔
64
}
3✔
65

66
int DetectBase64DecodeDoMatch(DetectEngineThreadCtx *det_ctx, const Signature *s,
67
    const SigMatchData *smd, const uint8_t *payload, uint32_t payload_len)
68
{
886✔
69
    DetectBase64Decode *data = (DetectBase64Decode *)smd->ctx;
886✔
70

71
#if 0
72
    printf("Input data:\n");
73
    PrintRawDataFp(stdout, payload, payload_len);
74
#endif
75

76
    if (data->relative) {
886✔
77
        payload += det_ctx->buffer_offset;
704✔
78
        DEBUG_VALIDATE_BUG_ON(det_ctx->buffer_offset > payload_len);
704✔
79
        payload_len -= det_ctx->buffer_offset;
704✔
80
    }
704✔
81

82
    if (data->offset) {
886✔
83
        if (data->offset >= payload_len) {
47✔
UNCOV
84
            return 0;
×
UNCOV
85
        }
×
86
        payload = payload + data->offset;
47✔
87
        payload_len -= data->offset;
47✔
88
    }
47✔
89

90
    uint32_t decode_len = MIN(payload_len, data->bytes);
886✔
91
#if 0
92
    printf("Decoding:\n");
93
    PrintRawDataFp(stdout, payload, decode_len);
94
#endif
95

96
    if (decode_len > 0) {
886✔
97
        uint32_t num_decoded =
881✔
98
                SCBase64Decode(payload, decode_len, SCBase64ModeRFC4648, det_ctx->base64_decoded);
881✔
99
        det_ctx->base64_decoded_len = num_decoded;
881✔
100
        SCLogDebug("Decoded %d bytes from base64 data.", det_ctx->base64_decoded_len);
881✔
101
    }
881✔
102
#if 0
103
    if (det_ctx->base64_decoded_len) {
104
        printf("Decoded data:\n");
105
        PrintRawDataFp(stdout, det_ctx->base64_decoded,
106
            det_ctx->base64_decoded_len);
107
    }
108
#endif
109

110
    return det_ctx->base64_decoded_len > 0;
886✔
111
}
886✔
112

113
static int DetectBase64DecodeParse(
114
        const char *str, uint16_t *bytes, uint32_t *offset, uint8_t *relative)
115
{
9,729✔
116
    const char *bytes_str = NULL;
9,729✔
117
    const char *offset_str = NULL;
9,729✔
118
    const char *relative_str = NULL;
9,729✔
119
    int retval = 0;
9,729✔
120

121
    *bytes = 0;
9,729✔
122
    *offset = 0;
9,729✔
123
    *relative = 0;
9,729✔
124
    size_t pcre2_len;
9,729✔
125
    pcre2_match_data *match = NULL;
9,729✔
126

127
    int pcre_rc = DetectParsePcreExec(&decode_pcre, &match, str, 0, 0);
9,729✔
128
    if (pcre_rc < 3) {
9,729✔
129
        goto error;
235✔
130
    }
235✔
131

132
    if (pcre_rc >= 3) {
9,494✔
133
        if (pcre2_substring_get_bynumber(match, 2, (PCRE2_UCHAR8 **)&bytes_str, &pcre2_len) == 0) {
9,494✔
134
            if (StringParseUint16(bytes, 10, 0, bytes_str) <= 0) {
2,777✔
135
                SCLogError("Bad value for bytes: \"%s\"", bytes_str);
1,613✔
136
                goto error;
1,613✔
137
            }
1,613✔
138
        }
2,777✔
139
     }
9,494✔
140

141
    if (pcre_rc >= 5) {
7,881✔
142
        if (pcre2_substring_get_bynumber(match, 4, (PCRE2_UCHAR8 **)&offset_str, &pcre2_len) == 0) {
7,502✔
143
            if (StringParseUint32(offset, 10, 0, offset_str) <= 0) {
619✔
144
                SCLogError("Bad value for offset: \"%s\"", offset_str);
56✔
145
                goto error;
56✔
146
            }
56✔
147
        }
619✔
148
    }
7,502✔
149

150
    if (pcre_rc >= 6) {
7,825✔
151
        if (pcre2_substring_get_bynumber(match, 5, (PCRE2_UCHAR8 **)&relative_str, &pcre2_len) ==
7,177✔
152
                0) {
7,177✔
153
            if (strcmp(relative_str, "relative") == 0) {
7,177✔
154
                *relative = 1;
6,340✔
155
            }
6,340✔
156
            else {
837✔
157
                SCLogError("Invalid argument: \"%s\"", relative_str);
837✔
158
                goto error;
837✔
159
            }
837✔
160
        }
7,177✔
161
    }
7,177✔
162

163
    retval = 1;
6,988✔
164

165
    pcre2_match_data_free(match);
6,988✔
166
    match = NULL;
6,988✔
167

168
error:
9,729✔
169

170
    if (bytes_str != NULL) {
9,729✔
171
        pcre2_substring_free((PCRE2_UCHAR8 *)bytes_str);
2,777✔
172
    }
2,777✔
173
    if (offset_str != NULL) {
9,729✔
174
        pcre2_substring_free((PCRE2_UCHAR8 *)offset_str);
619✔
175
    }
619✔
176
    if (relative_str != NULL) {
9,729✔
177
        pcre2_substring_free((PCRE2_UCHAR8 *)relative_str);
7,177✔
178
    }
7,177✔
179
    if (match) {
9,729✔
180
        pcre2_match_data_free(match);
2,741✔
181
    }
2,741✔
182
    return retval;
9,729✔
183
}
6,988✔
184

185
static int DetectBase64DecodeSetup(DetectEngineCtx *de_ctx, Signature *s,
186
    const char *str)
187
{
12,645✔
188
    uint16_t bytes = 0;
12,645✔
189
    uint32_t offset = 0;
12,645✔
190
    uint8_t relative = 0;
12,645✔
191
    DetectBase64Decode *data = NULL;
12,645✔
192
    int sm_list;
12,645✔
193
    SigMatch *pm = NULL;
12,645✔
194

195
    if (str != NULL) {
12,645✔
196
        if (!DetectBase64DecodeParse(str, &bytes, &offset, &relative)) {
9,729✔
197
            goto error;
2,741✔
198
        }
2,741✔
199
    }
9,729✔
200
    data = SCCalloc(1, sizeof(DetectBase64Decode));
9,904✔
201
    if (unlikely(data == NULL)) {
9,904✔
202
        goto error;
×
203
    }
×
204
    data->bytes = bytes;
9,904✔
205
    data->offset = offset;
9,904✔
206
    data->relative = relative;
9,904✔
207

208
    if (s->init_data->list != DETECT_SM_LIST_NOTSET) {
9,904✔
209
        sm_list = s->init_data->list;
6,653✔
210
    }
6,653✔
211
    else {
3,251✔
212
        pm = SCDetectGetLastSMFromLists(s, DETECT_CONTENT, DETECT_PCRE, DETECT_BYTETEST,
3,251✔
213
                DETECT_BYTEJUMP, DETECT_BYTE_EXTRACT, DETECT_ISDATAAT, -1);
3,251✔
214
        if (pm == NULL) {
3,251✔
215
            sm_list = DETECT_SM_LIST_PMATCH;
740✔
216
        }
740✔
217
        else {
2,511✔
218
            sm_list = SigMatchListSMBelongsTo(s, pm);
2,511✔
219
            if (sm_list < 0) {
2,511✔
220
                goto error;
×
221
            }
×
222
        }
2,511✔
223
    }
3,251✔
224

225
    if (SCSigMatchAppendSMToList(de_ctx, s, DETECT_BASE64_DECODE, (SigMatchCtx *)data, sm_list) ==
9,904✔
226
            NULL) {
9,904✔
227
        goto error;
×
228
    }
×
229

230
    if (!data->bytes) {
9,904✔
231
        data->bytes = BASE64_DECODE_MAX;
9,183✔
232
    }
9,183✔
233
    if (data->bytes > de_ctx->base64_decode_max_len) {
9,904✔
234
        de_ctx->base64_decode_max_len = data->bytes;
487✔
235
    }
487✔
236

237
    return 0;
9,904✔
238
error:
2,741✔
239
    if (data != NULL) {
2,741✔
240
        SCFree(data);
×
241
    }
×
242
    return -1;
2,741✔
243
}
9,904✔
244

245
static void DetectBase64DecodeFree(DetectEngineCtx *de_ctx, void *ptr)
246
{
9,904✔
247
    DetectBase64Decode *data = ptr;
9,904✔
248
    SCFree(data);
9,904✔
249
}
9,904✔
250

251

252
#ifdef UNITTESTS
253
#include "detect-engine.h"
254
#include "util-unittest.h"
255
#include "util-unittest-helper.h"
256
#include "app-layer-parser.h"
257
#include "flow-util.h"
258
#include "stream-tcp.h"
259

260
static int g_http_header_buffer_id = 0;
261

262
static int DetectBase64TestDecodeParse(void)
263
{
264
    int retval = 0;
265
    uint16_t bytes = 0;
266
    uint32_t offset = 0;
267
    uint8_t relative = 0;
268

269
    if (!DetectBase64DecodeParse("bytes 1", &bytes, &offset, &relative)) {
270
        goto end;
271
    }
272
    if (bytes != 1 || offset != 0 || relative != 0) {
273
        goto end;
274
    }
275

276
    if (!DetectBase64DecodeParse("offset 9", &bytes, &offset, &relative)) {
277
        goto end;
278
    }
279
    if (bytes != 0 || offset != 9 || relative != 0) {
280
        goto end;
281
    }
282

283
    if (!DetectBase64DecodeParse("relative", &bytes, &offset, &relative)) {
284
        goto end;
285
    }
286
    if (bytes != 0 || offset != 0 || relative != 1) {
287
        goto end;
288
    }
289

290
    if (!DetectBase64DecodeParse("bytes 1, offset 2", &bytes, &offset,
291
            &relative)) {
292
        goto end;
293
    }
294
    if (bytes != 1 || offset != 2 || relative != 0) {
295
        goto end;
296
    }
297

298
    if (!DetectBase64DecodeParse("bytes 1, offset 2, relative", &bytes, &offset,
299
            &relative)) {
300
        goto end;
301
    }
302
    if (bytes != 1 || offset != 2 || relative != 1) {
303
        goto end;
304
    }
305

306
    if (!DetectBase64DecodeParse("offset 2, relative", &bytes, &offset,
307
            &relative)) {
308
        goto end;
309
    }
310
    if (bytes != 0 || offset != 2 || relative != 1) {
311
        goto end;
312
    }
313

314
    /* Misspelled relative. */
315
    if (DetectBase64DecodeParse("bytes 1, offset 2, relatve", &bytes, &offset,
316
            &relative)) {
317
        goto end;
318
    }
319

320
    /* Misspelled bytes. */
321
    if (DetectBase64DecodeParse("byts 1, offset 2, relatve", &bytes, &offset,
322
            &relative)) {
323
        goto end;
324
    }
325

326
    /* Misspelled offset. */
327
    if (DetectBase64DecodeParse("bytes 1, offst 2, relatve", &bytes, &offset,
328
            &relative)) {
329
        goto end;
330
    }
331

332
    /* Misspelled empty string. */
333
    if (DetectBase64DecodeParse("", &bytes, &offset, &relative)) {
334
        goto end;
335
    }
336

337
    retval = 1;
338
end:
339
    return retval;
340
}
341

342
/**
343
 * Test keyword setup on basic content.
344
 */
345
static int DetectBase64DecodeTestSetup(void)
346
{
347
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
348
    FAIL_IF_NULL(de_ctx);
349

350
    Signature *s = DetectEngineAppendSig(de_ctx, "alert tcp any any -> any any ("
351
                                                 "base64_decode; content:\"content\"; "
352
                                                 "sid:1; rev:1;)");
353
    FAIL_IF_NULL(s);
354
    FAIL_IF_NULL(s->init_data->smlists_tail[DETECT_SM_LIST_PMATCH]);
355

356
    DetectEngineCtxFree(de_ctx);
357
    PASS;
358
}
359

360
static int DetectBase64DecodeTestDecode(void)
361
{
362
    ThreadVars tv;
363
    DetectEngineCtx *de_ctx = NULL;
364
    DetectEngineThreadCtx *det_ctx = NULL;
365
    Packet *p = NULL;
366
    int retval = 0;
367

368
    uint8_t payload[] = {
369
        'S', 'G', 'V', 's', 'b', 'G', '8', 'g',
370
        'V', '2', '9', 'y', 'b', 'G', 'Q', '=',
371
    };
372

373
    memset(&tv, 0, sizeof(tv));
374
    StatsThreadInit(&tv.stats);
375

376
    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
377
        goto end;
378
    }
379

380
    de_ctx->sig_list = SigInit(de_ctx,
381
        "alert tcp any any -> any any (msg:\"base64 test\"; "
382
        "base64_decode; "
383
        "sid:1; rev:1;)");
384
    if (de_ctx->sig_list == NULL) {
385
        goto end;
386
    }
387
    SigGroupBuild(de_ctx);
388
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
389

390
    p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
391
    if (p == NULL) {
392
        goto end;
393
    }
394

395
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
396
    if (det_ctx->base64_decoded_len == 0) {
397
        goto end;
398
    }
399

400
    retval = 1;
401
end:
402
    if (det_ctx != NULL) {
403
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
404
    }
405
    if (de_ctx != NULL) {
406
        DetectEngineCtxFree(de_ctx);
407
    }
408
    if (p != NULL) {
409
        UTHFreePacket(p);
410
    }
411
    StatsThreadCleanup(&tv.stats);
412
    return retval;
413
}
414

415
static int DetectBase64DecodeTestDecodeWithOffset(void)
416
{
417
    ThreadVars tv;
418
    DetectEngineCtx *de_ctx = NULL;
419
    DetectEngineThreadCtx *det_ctx = NULL;
420
    Packet *p = NULL;
421
    int retval = 0;
422

423
    uint8_t payload[] = {
424
        'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
425
        'S', 'G', 'V', 's', 'b', 'G', '8', 'g',
426
        'V', '2', '9', 'y', 'b', 'G', 'Q', '=',
427
    };
428
    char decoded[] = "Hello World";
429

430
    memset(&tv, 0, sizeof(tv));
431
    StatsThreadInit(&tv.stats);
432

433
    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
434
        goto end;
435
    }
436

437
    de_ctx->sig_list = SigInit(de_ctx,
438
        "alert tcp any any -> any any (msg:\"base64 test\"; "
439
        "base64_decode: offset 8; "
440
        "sid:1; rev:1;)");
441
    if (de_ctx->sig_list == NULL) {
442
        goto end;
443
    }
444
    SigGroupBuild(de_ctx);
445
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
446

447
    p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
448
    if (p == NULL) {
449
        goto end;
450
    }
451

452
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
453
    if (det_ctx->base64_decoded_len != (int)strlen(decoded)) {
454
        goto end;
455
    }
456
    if (memcmp(det_ctx->base64_decoded, decoded, strlen(decoded))) {
457
        goto end;
458
    }
459

460
    retval = 1;
461
end:
462
    if (det_ctx != NULL) {
463
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
464
    }
465
    if (de_ctx != NULL) {
466
        SigCleanSignatures(de_ctx);
467
        SigGroupCleanup(de_ctx);
468
        DetectEngineCtxFree(de_ctx);
469
    }
470
    if (p != NULL) {
471
        UTHFreePacket(p);
472
    }
473
    StatsThreadCleanup(&tv.stats);
474
    return retval;
475
}
476

477
static int DetectBase64DecodeTestDecodeLargeOffset(void)
478
{
479
    ThreadVars tv;
480
    DetectEngineCtx *de_ctx = NULL;
481
    DetectEngineThreadCtx *det_ctx = NULL;
482
    Packet *p = NULL;
483
    int retval = 0;
484

485
    uint8_t payload[] = {
486
        'S', 'G', 'V', 's', 'b', 'G', '8', 'g',
487
        'V', '2', '9', 'y', 'b', 'G', 'Q', '=',
488
    };
489

490
    memset(&tv, 0, sizeof(tv));
491
    StatsThreadInit(&tv.stats);
492

493
    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
494
        goto end;
495
    }
496

497
    /* Offset is out of range. */
498
    de_ctx->sig_list = SigInit(de_ctx,
499
        "alert tcp any any -> any any (msg:\"base64 test\"; "
500
        "base64_decode: bytes 16, offset 32; "
501
        "sid:1; rev:1;)");
502
    if (de_ctx->sig_list == NULL) {
503
        goto end;
504
    }
505
    SigGroupBuild(de_ctx);
506
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
507

508
    p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
509
    if (p == NULL) {
510
        goto end;
511
    }
512

513
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
514
    if (det_ctx->base64_decoded_len != 0) {
515
        goto end;
516
    }
517

518
    retval = 1;
519
end:
520
    if (det_ctx != NULL) {
521
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
522
    }
523
    if (de_ctx != NULL) {
524
        DetectEngineCtxFree(de_ctx);
525
    }
526
    if (p != NULL) {
527
        UTHFreePacket(p);
528
    }
529
    StatsThreadCleanup(&tv.stats);
530
    return retval;
531
}
532

533
static int DetectBase64DecodeTestDecodeRelative(void)
534
{
535
    ThreadVars tv;
536
    DetectEngineCtx *de_ctx = NULL;
537
    DetectEngineThreadCtx *det_ctx = NULL;
538
    Packet *p = NULL;
539
    int retval = 0;
540

541
    uint8_t payload[] = {
542
        'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
543
        'S', 'G', 'V', 's', 'b', 'G', '8', 'g',
544
        'V', '2', '9', 'y', 'b', 'G', 'Q', '=',
545
    };
546
    char decoded[] = "Hello World";
547

548
    memset(&tv, 0, sizeof(tv));
549
    StatsThreadInit(&tv.stats);
550

551
    if ((de_ctx = DetectEngineCtxInit()) == NULL) {
552
        goto end;
553
    }
554

555
    de_ctx->sig_list = SigInit(de_ctx,
556
        "alert tcp any any -> any any (msg:\"base64 test\"; "
557
        "content:\"aaaaaaaa\"; "
558
        "base64_decode: relative; "
559
        "sid:1; rev:1;)");
560
    if (de_ctx->sig_list == NULL) {
561
        goto end;
562
    }
563
    SigGroupBuild(de_ctx);
564
    DetectEngineThreadCtxInit(&tv, (void *)de_ctx, (void *)&det_ctx);
565

566
    p = UTHBuildPacket(payload, sizeof(payload), IPPROTO_TCP);
567
    if (p == NULL) {
568
        goto end;
569
    }
570

571
    SigMatchSignatures(&tv, de_ctx, det_ctx, p);
572
    if (det_ctx->base64_decoded_len != (int)strlen(decoded)) {
573
        goto end;
574
    }
575
    if (memcmp(det_ctx->base64_decoded, decoded, strlen(decoded))) {
576
        goto end;
577
    }
578

579
    retval = 1;
580
end:
581
    if (det_ctx != NULL) {
582
        DetectEngineThreadCtxDeinit(&tv, det_ctx);
583
    }
584
    if (de_ctx != NULL) {
585
        DetectEngineCtxFree(de_ctx);
586
    }
587
    if (p != NULL) {
588
        UTHFreePacket(p);
589
    }
590
    StatsThreadCleanup(&tv.stats);
591
    return retval;
592
}
593

594
static void DetectBase64DecodeRegisterTests(void)
595
{
596
    g_http_header_buffer_id = DetectBufferTypeGetByName("http_header");
597

598
    UtRegisterTest("DetectBase64TestDecodeParse", DetectBase64TestDecodeParse);
599
    UtRegisterTest("DetectBase64DecodeTestSetup", DetectBase64DecodeTestSetup);
600
    UtRegisterTest("DetectBase64DecodeTestDecode",
601
                   DetectBase64DecodeTestDecode);
602
    UtRegisterTest("DetectBase64DecodeTestDecodeWithOffset",
603
                   DetectBase64DecodeTestDecodeWithOffset);
604
    UtRegisterTest("DetectBase64DecodeTestDecodeLargeOffset",
605
                   DetectBase64DecodeTestDecodeLargeOffset);
606
    UtRegisterTest("DetectBase64DecodeTestDecodeRelative",
607
                   DetectBase64DecodeTestDecodeRelative);
608
}
609
#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