Coverage Report

Created: 2026-02-14 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/tests/fuzz/fuzz_sigpcap.c
Line
Count
Source
1
/**
2
 * @file
3
 * @author Philippe Antoine <contact@catenacyber.fr>
4
 * fuzz target for signature file and pcap file
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 "flow-worker.h"
28
#include "tm-modules.h"
29
#include "tmqh-packetpool.h"
30
#include "util-file.h"
31
#include "util-conf.h"
32
#include "packet.h"
33
34
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size);
35
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
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
48
32.1k
{
49
32.1k
    pcap_t * pkts;
50
32.1k
    char errbuf[PCAP_ERRBUF_SIZE];
51
32.1k
    const u_char *pkt;
52
32.1k
    struct pcap_pkthdr *header;
53
32.1k
    int r;
54
32.1k
    Packet *p;
55
32.1k
    size_t pos;
56
32.1k
    size_t pcap_cnt = 0;
57
58
32.1k
    if (initialized == 0) {
59
        //Redirects logs to /dev/null
60
1
        setenv("SC_LOG_OP_IFACE", "file", 0);
61
1
        setenv("SC_LOG_FILE", "/dev/null", 0);
62
63
1
        InitGlobal();
64
65
1
        GlobalsInitPreConfig();
66
1
        run_mode = RUNMODE_PCAP_FILE;
67
        //redirect logs to /tmp
68
1
        ConfigSetLogDirectory("/tmp/");
69
        //disables checksums validation for fuzzing
70
1
        if (ConfYamlLoadString(configNoChecksum, strlen(configNoChecksum)) != 0) {
71
0
            abort();
72
0
        }
73
        // do not load rules before reproducible DetectEngineReload
74
1
        remove("/tmp/fuzz.rules");
75
1
        surifuzz.sig_file = strdup("/tmp/fuzz.rules");
76
1
        surifuzz.sig_file_exclusive = 1;
77
        //loads rules after init
78
1
        surifuzz.delayed_detect = 1;
79
80
1
        PostConfLoadedSetup(&surifuzz);
81
1
        PreRunPostPrivsDropInit(run_mode);
82
1
        PostConfLoadedDetectSetup(&surifuzz);
83
84
1
        memset(&tv, 0, sizeof(tv));
85
1
        tv.flow_queue = FlowQueueNew();
86
1
        if (tv.flow_queue == NULL)
87
0
            abort();
88
1
        dtv = DecodeThreadVarsAlloc(&tv);
89
1
        DecodeRegisterPerfCounters(dtv, &tv);
90
1
        tmm_modules[TMM_FLOWWORKER].ThreadInit(&tv, NULL, &fwd);
91
1
        StatsSetupPrivate(&tv);
92
93
1
        extern uint16_t max_pending_packets;
94
1
        max_pending_packets = 128;
95
1
        PacketPoolInit();
96
1
        SC_ATOMIC_SET(engine_stage, SURICATA_RUNTIME);
97
1
        initialized = 1;
98
1
    }
99
100
    /* TODO add yaml config
101
     for (pos = 0; pos < size; pos++) {
102
        if (data[pos] == 0) {
103
            break;
104
        }
105
    }
106
    if (ConfYamlLoadString(data, pos) != 0) {
107
        return 0;
108
    }
109
    if (pos < size) {
110
        //skip zero
111
        pos++;
112
    }
113
    data += pos;
114
    size -= pos;*/
115
116
662M
    for (pos=0; pos < size; pos++) {
117
662M
        if (data[pos] == 0) {
118
16.6k
            break;
119
16.6k
        }
120
662M
    }
121
32.1k
    if (pos > 0 && pos < size) {
122
        // dump signatures to a file so as to reuse SigLoadSignatures
123
14.2k
        if (TestHelperBufferToFile(surifuzz.sig_file, data, pos-1) < 0) {
124
0
            return 0;
125
0
        }
126
17.9k
    } else {
127
17.9k
        if (TestHelperBufferToFile(surifuzz.sig_file, data, pos) < 0) {
128
0
            return 0;
129
0
        }
130
17.9k
    }
131
132
32.1k
    if (DetectEngineReload(&surifuzz) < 0) {
133
0
        return 0;
134
0
    }
135
32.1k
    DetectEngineThreadCtx *old_det_ctx = FlowWorkerGetDetectCtxPtr(fwd);
136
137
32.1k
    DetectEngineCtx *de_ctx = DetectEngineGetCurrent();
138
32.1k
    de_ctx->ref_cnt--;
139
32.1k
    DetectEngineThreadCtx *new_det_ctx = DetectEngineThreadCtxInitForReload(&tv, de_ctx, 1);
140
32.1k
    FlowWorkerReplaceDetectCtx(fwd, new_det_ctx);
141
142
32.1k
    DetectEngineThreadCtxDeinit(NULL, old_det_ctx);
143
144
32.1k
    if (pos < size) {
145
        //skip zero
146
16.6k
        pos++;
147
16.6k
    }
148
32.1k
    data += pos;
149
32.1k
    size -= pos;
150
151
    //rewrite buffer to a file as libpcap does not have buffer inputs
152
32.1k
    if (TestHelperBufferToFile("/tmp/fuzz.pcap", data, size) < 0) {
153
0
        return 0;
154
0
    }
155
156
    //initialize structure
157
32.1k
    pkts = pcap_open_offline("/tmp/fuzz.pcap", errbuf);
158
32.1k
    if (pkts == NULL) {
159
18.4k
        return 0;
160
18.4k
    }
161
162
    //loop over packets
163
13.7k
    r = pcap_next_ex(pkts, &header, &pkt);
164
13.7k
    p = PacketGetFromAlloc();
165
13.7k
    if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
166
330
        goto bail;
167
330
    }
168
13.4k
    p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
169
13.4k
    p->datalink = pcap_datalink(pkts);
170
13.4k
    p->pkt_src = PKT_SRC_WIRE;
171
711k
    while (r > 0) {
172
711k
        if (PacketCopyData(p, pkt, header->caplen) == 0) {
173
            // DecodePcapFile
174
711k
            TmEcode ecode = tmm_modules[TMM_DECODEPCAPFILE].Func(&tv, p, dtv);
175
711k
            if (ecode == TM_ECODE_FAILED) {
176
96
                break;
177
96
            }
178
711k
            Packet *extra_p = PacketDequeueNoLock(&tv.decode_pq);
179
712k
            while (extra_p != NULL) {
180
1.43k
                PacketFreeOrRelease(extra_p);
181
1.43k
                extra_p = PacketDequeueNoLock(&tv.decode_pq);
182
1.43k
            }
183
711k
            tmm_modules[TMM_FLOWWORKER].Func(&tv, p, fwd);
184
711k
            extra_p = PacketDequeueNoLock(&tv.decode_pq);
185
711k
            while (extra_p != NULL) {
186
0
                PacketFreeOrRelease(extra_p);
187
0
                extra_p = PacketDequeueNoLock(&tv.decode_pq);
188
0
            }
189
711k
        }
190
711k
        r = pcap_next_ex(pkts, &header, &pkt);
191
711k
        if (r <= 0 || header->ts.tv_sec >= INT_MAX - 3600 || header->ts.tv_usec < 0) {
192
13.3k
            goto bail;
193
13.3k
        }
194
698k
        PacketRecycle(p);
195
698k
        p->ts = SCTIME_FROM_TIMEVAL(&header->ts);
196
698k
        p->datalink = pcap_datalink(pkts);
197
698k
        p->pkt_src = PKT_SRC_WIRE;
198
698k
        pcap_cnt++;
199
698k
        p->pcap_cnt = pcap_cnt;
200
698k
    }
201
13.7k
bail:
202
    //close structure
203
13.7k
    pcap_close(pkts);
204
13.7k
    PacketFree(p);
205
13.7k
    FlowReset();
206
207
13.7k
    return 0;
208
13.4k
}