/src/rtpproxy/scripts/fuzz/fuzz_rtp_session.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include <sys/types.h> |
2 | | #include <sys/socket.h> |
3 | | #include <netinet/in.h> |
4 | | #include <arpa/inet.h> |
5 | | #include <assert.h> |
6 | | #include <semaphore.h> |
7 | | #include <stdio.h> |
8 | | #include <stdlib.h> |
9 | | #include <string.h> |
10 | | |
11 | | #include "fuzz_standalone.h" |
12 | | |
13 | | #define HAVE_CONFIG_H 1 |
14 | | #include "config_pp.h" |
15 | | |
16 | | #include "rtpp_types.h" |
17 | | #include "rtpp_cfg.h" |
18 | | #include "rtp.h" |
19 | | #include "rtpp_time.h" |
20 | | #include "rtpp_codeptr.h" |
21 | | #include "rtp_packet.h" |
22 | | #include "rtpp_session.h" |
23 | | #include "rtpp_pipe.h" |
24 | | #include "rtpp_proc.h" |
25 | | #include "rtpp_network.h" |
26 | | #include "rtpp_stream.h" |
27 | | #include "rtpp_ttl.h" |
28 | | #include "rtpp_codeptr.h" |
29 | | #include "rtpp_refcnt.h" |
30 | | #include "rtpp_command.h" |
31 | | #include "rtpp_weakref.h" |
32 | | #include "rtpp_hash_table.h" |
33 | | #include "advanced/packet_processor.h" |
34 | | #include "advanced/pproc_manager.h" |
35 | | |
36 | | #include "rfz_chunk.h" |
37 | | #include "rfz_utils.h" |
38 | | #include "rfz_command.h" |
39 | | |
40 | | static struct { |
41 | | sem_t wi_proc_done; |
42 | | } fuzz_ctx; |
43 | | |
44 | | static void |
45 | | fuzz_ctx_dtor(void) |
46 | 2 | { |
47 | 2 | ExecuteRTPPCommand(&gconf, "X", 1, 0); |
48 | 2 | sem_destroy(&fuzz_ctx.wi_proc_done); |
49 | 2 | } |
50 | | |
51 | | static const char * const setup_script[] = { |
52 | | #include "fuzz_rtp_session.setup" |
53 | | NULL |
54 | | }; |
55 | | |
56 | | static int |
57 | | ExecuteScript(void) |
58 | 3.70k | { |
59 | 3.70k | char line[RTPP_CMD_BUFLEN]; |
60 | | |
61 | 33.3k | for (int i = 0; setup_script[i] != NULL; i++) { |
62 | 29.6k | const char *cp = setup_script[i]; |
63 | 29.6k | int size = strlen(cp); |
64 | 29.6k | memcpy(line, cp, size + 1); |
65 | 29.6k | int r = ExecuteRTPPCommand(&gconf, line, size, 0); |
66 | 29.6k | if (r != 0) |
67 | 0 | return (-1); |
68 | 29.6k | } |
69 | 3.70k | return (0); |
70 | 3.70k | } |
71 | | |
72 | | int |
73 | | LLVMFuzzerInitialize(int *_argc, char ***_argv) |
74 | 2 | { |
75 | 2 | RTPPInitializeParams.ttl = "60"; |
76 | 2 | int r = RTPPInitialize(); |
77 | | |
78 | 2 | if (r != 0) |
79 | 0 | goto e0; |
80 | 2 | if (sem_init(&fuzz_ctx.wi_proc_done, 0, 0) != 0) |
81 | 0 | goto e0; |
82 | 2 | if (ExecuteScript() != 0) |
83 | 0 | goto e1; |
84 | 2 | if (ExecuteRTPPCommand(&gconf, "X", 1, 0) != 0) |
85 | 0 | goto e1; |
86 | 2 | atexit(fuzz_ctx_dtor); |
87 | 2 | return (0); |
88 | 0 | e1: |
89 | 0 | sem_destroy(&fuzz_ctx.wi_proc_done); |
90 | 0 | e0: |
91 | 0 | return (-1); |
92 | 0 | } |
93 | | |
94 | | struct foreach_args { |
95 | | const char *data; |
96 | | size_t size; |
97 | | struct rtpp_proc_rstats *rsp; |
98 | | int nwait; |
99 | | }; |
100 | | |
101 | | static void |
102 | | wi_proc_complete(void *arg) |
103 | 337k | { |
104 | 337k | sem_post(&fuzz_ctx.wi_proc_done); |
105 | 337k | } |
106 | | |
107 | | static int |
108 | | proc_foreach(void *dp, void *ap) |
109 | 168k | { |
110 | 168k | struct foreach_args *fap; |
111 | 168k | const struct rtpp_session *sp; |
112 | 168k | rtpp_refcnt_dtor_t wpd_f = (rtpp_refcnt_dtor_t)&wi_proc_complete; |
113 | | |
114 | 168k | fap = (struct foreach_args *)ap; |
115 | | /* |
116 | | * This method does not need us to bump ref, since we are in the |
117 | | * locked context of the rtpp_hash_table, which holds its own ref. |
118 | | */ |
119 | 168k | sp = (const struct rtpp_session *)dp; |
120 | | |
121 | 506k | for (int i=0; i < 2; i++) { |
122 | 337k | struct sockaddr *rap; |
123 | 337k | struct rtp_packet *pktp = rtp_packet_alloc(); |
124 | 337k | assert (pktp != NULL); |
125 | 337k | void *olddata = CALL_SMETHOD(pktp->rcnt, getdata); |
126 | 337k | CALL_SMETHOD(pktp->rcnt, attach, wpd_f, olddata); |
127 | 337k | rap = sstosa(&pktp->raddr); |
128 | 337k | memcpy(rap, fap->data, sizeof(struct sockaddr_in)); |
129 | 337k | rap->sa_family = AF_INET; |
130 | 337k | pktp->size = fap->size - sizeof(struct sockaddr_in); |
131 | 337k | memcpy(pktp->data.buf, fap->data + sizeof(struct sockaddr_in), pktp->size); |
132 | 337k | struct rtpp_stream *istp = sp->rtp->stream[i], |
133 | 337k | *ostp = sp->rtp->stream[i ^ 1]; |
134 | 337k | struct pkt_proc_ctx pktx = {.strmp_in = istp, |
135 | 337k | .strmp_out = ostp, |
136 | 337k | .rsp = fap->rsp, |
137 | 337k | .pktp = pktp}; |
138 | 337k | CALL_SMETHOD(istp->pproc_manager, handleat, &pktx, _PPROC_ORD_EMPTY); |
139 | 337k | fap->nwait += 1; |
140 | 337k | } |
141 | 168k | return (RTPP_HT_MATCH_CONT); |
142 | 168k | } |
143 | | |
144 | | int |
145 | | LLVMFuzzerTestOneInput(const char *data, size_t size) |
146 | 3.70k | { |
147 | 3.70k | static struct rtpp_proc_rstats rs = {0}; |
148 | 3.70k | sem_t *wpdp = &fuzz_ctx.wi_proc_done; |
149 | 3.70k | struct { |
150 | 3.70k | union { |
151 | 3.70k | struct { |
152 | 3.70k | uint8_t reseed:1; |
153 | 3.70k | }; |
154 | 3.70k | uint8_t value; |
155 | 3.70k | }; |
156 | 3.70k | } op_flags; |
157 | | |
158 | 3.70k | if (size < 2) |
159 | 1 | return (0); |
160 | | |
161 | 3.70k | op_flags.value = data[0]; |
162 | 3.70k | data += 1; |
163 | 3.70k | size -= 1; |
164 | | |
165 | 3.70k | if (op_flags.reseed) { |
166 | 1.31k | SeedRNGs(); |
167 | 1.31k | } |
168 | | |
169 | 3.70k | assert(ExecuteScript() == 0); |
170 | | |
171 | 3.70k | struct rfz_chunk chunk = {.rem_size = size, .rem_data = data}; |
172 | 3.70k | struct foreach_args fa = {.rsp = &rs}; |
173 | | |
174 | 34.2k | do { |
175 | 34.2k | chunk = rfz_get_chunk(chunk.rem_data, chunk.rem_size); |
176 | 34.2k | if (chunk.size < sizeof(struct sockaddr_in)) |
177 | 419 | break; |
178 | 33.7k | if (chunk.size > sizeof(struct sockaddr_in) + MAX_RPKT_LEN) |
179 | 0 | break; |
180 | 33.7k | fa.data = chunk.data; |
181 | 33.7k | fa.size = chunk.size; |
182 | 33.7k | CALL_SMETHOD(gconf.cfsp->sessions_ht, foreach, proc_foreach, (void *)&fa, NULL); |
183 | 33.7k | } while (chunk.rem_size > 1); |
184 | 341k | for (int i = 0; i < fa.nwait; i++) |
185 | 337k | sem_wait(wpdp); |
186 | | |
187 | 3.70k | assert(ExecuteRTPPCommand(&gconf, "X", 1, 0) == 0); |
188 | 3.70k | return (0); |
189 | 3.70k | } |