Coverage Report

Created: 2026-05-16 07:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
Line
Count
Source
1
/**
2
 * @file
3
 * @author Philippe Antoine <contact@catenacyber.fr>
4
 * fuzz target for AppLayerProtoDetectGetProto
5
 */
6
7
8
#include "suricata-common.h"
9
#include "suricata.h"
10
#include "app-layer-detect-proto.h"
11
#include "flow-util.h"
12
#include "app-layer-parser.h"
13
#include "util-unittest-helper.h"
14
#include "conf-yaml-loader.h"
15
16
2.33M
#define HEADER_LEN 6
17
18
//rule of thumb constant, so as not to timeout target
19
761k
#define PROTO_DETECT_MAX_LEN 1024
20
21
extern const char *configNoChecksum;
22
23
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
24
25
AppLayerProtoDetectThreadCtx *alpd_tctx = NULL;
26
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
27
28
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
29
13.5k
{
30
13.5k
    Flow *f;
31
13.5k
    TcpSession ssn;
32
13.5k
    bool reverse;
33
13.5k
    AppProto alproto;
34
13.5k
    AppProto alproto2;
35
36
13.5k
    if (alpd_tctx == NULL) {
37
        //global init
38
1
        InitGlobal();
39
1
        run_mode = RUNMODE_UNITTEST;
40
1
        if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
41
0
            abort();
42
0
        }
43
1
        MpmTableSetup();
44
1
        SpmTableSetup();
45
1
        EngineModeSetIDS();
46
1
        AppLayerProtoDetectSetup();
47
1
        AppLayerParserSetup();
48
1
        AppLayerParserRegisterProtocolParsers();
49
1
        alpd_tctx = AppLayerProtoDetectGetCtxThread();
50
1
        SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
51
1
    }
52
53
13.5k
    if (size < HEADER_LEN) {
54
3
        return 0;
55
3
    }
56
57
13.5k
    f = TestHelperBuildFlow(AF_INET, "1.2.3.4", "5.6.7.8", (uint16_t)((data[2] << 8) | data[3]),
58
13.5k
            (uint16_t)((data[4] << 8) | data[5]));
59
13.5k
    if (f == NULL) {
60
0
        return 0;
61
0
    }
62
13.5k
    f->proto = data[1];
63
13.5k
    memset(&ssn, 0, sizeof(TcpSession));
64
13.5k
    f->protoctx = &ssn;
65
13.5k
    f->protomap = FlowGetProtoMapping(f->proto);
66
67
13.5k
    uint8_t flags = STREAM_TOCLIENT;
68
13.5k
    if (data[0] & STREAM_TOSERVER) {
69
7.10k
        flags = STREAM_TOSERVER;
70
7.10k
    }
71
13.5k
    alproto = AppLayerProtoDetectGetProto(
72
13.5k
            alpd_tctx, f, data + HEADER_LEN, size - HEADER_LEN, f->proto, flags, &reverse);
73
13.5k
    if (alproto != ALPROTO_UNKNOWN && alproto != ALPROTO_FAILED && f->proto == IPPROTO_TCP) {
74
        /* If we find a valid protocol at the start of a stream :
75
         * check that with smaller input
76
         * we find the same protocol or ALPROTO_UNKNOWN.
77
         * Otherwise, we have evasion with TCP splitting
78
         */
79
765k
        for (size_t i = 0; i < size-HEADER_LEN && i < PROTO_DETECT_MAX_LEN; i++) {
80
            // reset detection at each try cf probing_parser_toserver_alproto_masks
81
760k
            AppLayerProtoDetectReset(f);
82
760k
            alproto2 = AppLayerProtoDetectGetProto(
83
760k
                    alpd_tctx, f, data + HEADER_LEN, i, f->proto, flags, &reverse);
84
760k
            if (alproto2 != ALPROTO_UNKNOWN && alproto2 != alproto) {
85
0
                printf("Failed with input length %" PRIuMAX " versus %" PRIuMAX
86
0
                       ", found %s instead of %s\n",
87
0
                        (uintmax_t)i, (uintmax_t)size - HEADER_LEN, AppProtoToString(alproto2),
88
0
                        AppProtoToString(alproto));
89
0
                printf("Assertion failure: %s-%s\n", AppProtoToString(alproto2),
90
0
                        AppProtoToString(alproto));
91
0
                fflush(stdout);
92
0
                abort();
93
0
            }
94
760k
        }
95
4.65k
    }
96
13.5k
    FlowFree(f);
97
98
13.5k
    return 0;
99
13.5k
}