/src/tcpreplay/test/fuzz/fuzz_services.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2026 Fred Klassen <tcpreplay.dev at gmail dot com> - AppNeta by Broadcom |
3 | | * |
4 | | * The Tcpreplay Suite of tools is free software: you can redistribute it |
5 | | * and/or modify it under the terms of the GNU General Public License as |
6 | | * published by the Free Software Foundation, either version 3 of the |
7 | | * License, or with the authors permission any later version. |
8 | | * |
9 | | * The Tcpreplay Suite is distributed in the hope that it will be useful, |
10 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | * GNU General Public License for more details. |
13 | | * |
14 | | * You should have received a copy of the GNU General Public License |
15 | | * along with the Tcpreplay Suite. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | |
18 | | /* |
19 | | * Fuzz target: the tcpprep --services file parser. |
20 | | * |
21 | | * GHSA-fwcr-mqg6-hqmx (CWE-121) lived here. parse_services() matched each |
22 | | * line against "([0-9]+)/(tcp|udp)" and copied the port substring into a |
23 | | * 10-byte stack buffer using the *regex match length* as the count. The digit |
24 | | * group is unbounded, so a long enough run of digits before /tcp overflowed |
25 | | * the buffer - and at larger sizes gave strncpy overlapping source and |
26 | | * destination. |
27 | | * |
28 | | * A fuzzer reaches that in seconds: the input is a text file, and the |
29 | | * interesting shape is "lots of digits, then a slash". This target exists so |
30 | | * the next one of those is found here rather than in someone's inbox. |
31 | | */ |
32 | | |
33 | | #include "fuzz_common.h" |
34 | | |
35 | | #include "defines.h" /* tcpr_services_t, before services.h uses it */ |
36 | | #include "common/services.h" |
37 | | |
38 | | int |
39 | | LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) |
40 | 82 | { |
41 | | /* |
42 | | * tcpr_services_t is two 64KB arrays. Keep it static rather than putting |
43 | | * 128KB on the stack every iteration - libFuzzer runs this millions of |
44 | | * times, and a stack overflow here would be the harness's fault, not the |
45 | | * code's. |
46 | | */ |
47 | 82 | static tcpr_services_t services; |
48 | 82 | char path[FUZZ_PATH_MAX]; |
49 | | |
50 | | /* parse_services() takes a filename, so the input has to reach the disk */ |
51 | 82 | if (fuzz_write_tempfile(data, size, path, sizeof(path)) != 0) |
52 | 0 | return 0; |
53 | | |
54 | 82 | memset(&services, 0, sizeof(services)); |
55 | 82 | parse_services(path, &services); |
56 | | |
57 | 82 | unlink(path); |
58 | 82 | return 0; |
59 | 82 | } |