Coverage Report

Created: 2025-07-23 07:29

/src/suricata7/src/tests/fuzz/fuzz_applayerprotodetectgetproto.c
Line
Count
Source (jump to first uncovered line)
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.45M
#define HEADER_LEN 6
17
18
//rule of thumb constant, so as not to timeout target
19
801k
#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
12.8k
{
30
12.8k
    Flow *f;
31
12.8k
    TcpSession ssn;
32
12.8k
    bool reverse;
33
12.8k
    AppProto alproto;
34
12.8k
    AppProto alproto2;
35
36
12.8k
    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
12.8k
    if (size < HEADER_LEN) {
54
3
        return 0;
55
3
    }
56
57
12.8k
    f = TestHelperBuildFlow(AF_INET, "1.2.3.4", "5.6.7.8", (uint16_t)((data[2] << 8) | data[3]),
58
12.8k
            (uint16_t)((data[4] << 8) | data[5]));
59
12.8k
    if (f == NULL) {
60
0
        return 0;
61
0
    }
62
12.8k
    f->proto = data[1];
63
12.8k
    memset(&ssn, 0, sizeof(TcpSession));
64
12.8k
    f->protoctx = &ssn;
65
12.8k
    f->protomap = FlowGetProtoMapping(f->proto);
66
67
12.8k
    uint8_t flags = STREAM_TOCLIENT;
68
12.8k
    if (data[0] & STREAM_TOSERVER) {
69
6.33k
        flags = STREAM_TOSERVER;
70
6.33k
    }
71
12.8k
    alproto = AppLayerProtoDetectGetProto(
72
12.8k
            alpd_tctx, f, data + HEADER_LEN, size - HEADER_LEN, f->proto, flags, &reverse);
73
12.8k
    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
805k
        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
801k
            AppLayerProtoDetectReset(f);
82
801k
            alproto2 = AppLayerProtoDetectGetProto(
83
801k
                    alpd_tctx, f, data + HEADER_LEN, i, f->proto, flags, &reverse);
84
801k
            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
801k
        }
95
4.73k
    }
96
12.8k
    FlowFree(f);
97
98
12.8k
    return 0;
99
12.8k
}