Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/tests/fuzz/fuzz_predefpcap_aware.c
Line
Count
Source
1
/**
2
 * @file
3
 * @author Philippe Antoine <contact@catenacyber.fr>
4
 * fuzz target for predefined signatures and pcap (aware)
5
 */
6
7
#include "suricata-common.h"
8
#include "source-pcap-file.h"
9
#include "detect-engine.h"
10
#include "util-classification-config.h"
11
#include "util-reference-config.h"
12
#include "app-layer.h"
13
#include "tm-queuehandlers.h"
14
#include "util-cidr.h"
15
#include "util-profiling.h"
16
#include "util-proto-name.h"
17
#include "detect-engine-tag.h"
18
#include "detect-engine-threshold.h"
19
#include "host-bit.h"
20
#include "ippair-bit.h"
21
#include "app-layer-htp.h"
22
#include "detect-fast-pattern.h"
23
#include "util-unittest-helper.h"
24
#include "conf-yaml-loader.h"
25
#include "pkt-var.h"
26
#include "flow-util.h"
27
#include "tm-modules.h"
28
#include "tmqh-packetpool.h"
29
#include "util-conf.h"
30
#include "packet.h"
31
32
#include <fuzz_pcap.h>
33
34
int LLVMFuzzerInitialize(const int *argc, char ***argv);
35
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
36
37
static int initialized = 0;
38
ThreadVars tv;
39
DecodeThreadVars *dtv;
40
// FlowWorkerThreadData
41
void *fwd;
42
SCInstance surifuzz;
43
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
44
45
extern const char *configNoChecksum;
46
47
char *filepath = NULL;
48
49
int LLVMFuzzerInitialize(const int *argc, char ***argv)
50
2
{
51
2
    filepath = dirname(strdup((*argv)[0]));
52
2
    return 0;
53
2
}
54
55
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
56
{
57
    FPC_buffer_t pkts;
58
    const u_char *pkt;
59
    struct pcap_pkthdr header;
60
    int r;
61
    Packet *p;
62
    size_t pcap_cnt = 0;
63
64
    if (initialized == 0) {
65
        // Redirects logs to /dev/null
66
        setenv("SC_LOG_OP_IFACE", "file", 0);
67
        setenv("SC_LOG_FILE", "/dev/null", 0);
68
69
        InitGlobal();
70
71
        GlobalsInitPreConfig();
72
        run_mode = RUNMODE_PCAP_FILE;
73
        // redirect logs to /tmp
74
        ConfigSetLogDirectory("/tmp/");
75
        // disables checksums validation for fuzzing
76
        if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
77
            abort();
78
        }
79
        surifuzz.sig_file = malloc(strlen(filepath) + strlen("/fuzz.rules") + 1);
80
        memcpy(surifuzz.sig_file, filepath, strlen(filepath));
81
        memcpy(surifuzz.sig_file + strlen(filepath), "/fuzz.rules", strlen("/fuzz.rules"));
82
        surifuzz.sig_file[strlen(filepath) + strlen("/fuzz.rules")] = 0;
83
        surifuzz.sig_file_exclusive = 1;
84
        // loads rules after init
85
        surifuzz.delayed_detect = 1;
86
87
        PostConfLoadedSetup(&surifuzz);
88
        PreRunPostPrivsDropInit(run_mode);
89
        PostConfLoadedDetectSetup(&surifuzz);
90
91
        memset(&tv, 0, sizeof(tv));
92
        tv.flow_queue = FlowQueueNew();
93
        if (tv.flow_queue == NULL)
94
            abort();
95
        dtv = DecodeThreadVarsAlloc(&tv);
96
        DecodeRegisterPerfCounters(dtv, &tv);
97
        tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
98
        StatsSetupPrivate(&tv);
99
100
        extern uint16_t max_pending_packets;
101
        max_pending_packets = 128;
102
        PacketPoolInit();
103
        if (DetectEngineReload(&surifuzz) < 0) {
104
            return 0;
105
        }
106
107
        SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
108
        initialized = 1;
109
    }
110
111
    if (size < FPC0_HEADER_LEN) {
112
        return 0;
113
    }
114
    // initialize FPC with the buffer
115
    if (FPC_init(&pkts, data, size) < 0) {
116
        return 0;
117
    }
118
119
    // loop over packets
120
    r = FPC_next(&pkts, &header, &pkt);
121
    p = PacketGetFromAlloc();
122
    if (p == NULL || r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
123
        goto bail;
124
    }
125
    p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
126
    p->datalink = pkts.datalink;
127
    p->pkt_src = PKT_SRC_WIRE;
128
    while (r > 0) {
129
        if (PacketCopyData(p, pkt, header.caplen) == 0) {
130
            // DecodePcapFile
131
            TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
132
            if (ecode == TM_ECODE_FAILED) {
133
                break;
134
            }
135
            Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
136
            while (extra_p != NULL) {
137
                PacketFreeOrRelease(extra_p);
138
                extra_p = PacketDequeueNoLock(&tv.decode_pq);
139
            }
140
            tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
141
            extra_p = PacketDequeueNoLock(&tv.decode_pq);
142
            while (extra_p != NULL) {
143
                PacketFreeOrRelease(extra_p);
144
                extra_p = PacketDequeueNoLock(&tv.decode_pq);
145
            }
146
        }
147
        r = FPC_next(&pkts, &header, &pkt);
148
        if (r <= 0 || header.ts.tv_sec >= INT_MAX - 3600) {
149
            goto bail;
150
        }
151
        PacketRecycle(p);
152
        p->ts = SCTIME_FROM_TIMEVAL(&header.ts);
153
        p->datalink = pkts.datalink;
154
        pcap_cnt++;
155
        p->pcap_cnt = pcap_cnt;
156
        p->pkt_src = PKT_SRC_WIRE;
157
    }
158
bail:
159
    if (p != NULL) {
160
        PacketFree(p);
161
    }
162
    FlowReset();
163
164
    return 0;
165
}