Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2016,2017 DeNA Co., Ltd., Kazuho Oku, Fastly |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
5 | | * of this software and associated documentation files (the "Software"), to |
6 | | * deal in the Software without restriction, including without limitation the |
7 | | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or |
8 | | * sell copies of the Software, and to permit persons to whom the Software is |
9 | | * furnished to do so, subject to the following conditions: |
10 | | * |
11 | | * The above copyright notice and this permission notice shall be included in |
12 | | * all copies or substantial portions of the Software. |
13 | | * |
14 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
15 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
16 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
17 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
18 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
19 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
20 | | * IN THE SOFTWARE. |
21 | | */ |
22 | | #ifndef util_h |
23 | | #define util_h |
24 | | |
25 | | #ifndef _XOPEN_SOURCE |
26 | | #define _XOPEN_SOURCE 700 /* required for glibc to use getaddrinfo, etc. */ |
27 | | #endif |
28 | | |
29 | | #include <errno.h> |
30 | | #include <netdb.h> |
31 | | #include <netinet/in.h> |
32 | | #include <stdio.h> |
33 | | #include <string.h> |
34 | | #include <sys/param.h> |
35 | | #include <sys/socket.h> |
36 | | #include <sys/types.h> |
37 | | #include <arpa/nameser.h> |
38 | | #include <resolv.h> |
39 | | #include <openssl/pem.h> |
40 | | #include "picotls/pembase64.h" |
41 | | #include "picotls/openssl.h" |
42 | | |
43 | | static inline void load_certificate_chain(ptls_context_t *ctx, const char *fn) |
44 | 0 | { |
45 | 0 | if (ptls_load_certificates(ctx, (char *)fn) != 0) { |
46 | 0 | fprintf(stderr, "failed to load certificate:%s:%s\n", fn, strerror(errno)); |
47 | 0 | exit(1); |
48 | 0 | } |
49 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:load_certificate_chain Unexecuted instantiation: fuzz-client-hello.c:load_certificate_chain |
50 | | |
51 | | static inline void load_raw_public_key(ptls_iovec_t *raw_public_key, char const *cert_pem_file) |
52 | 0 | { |
53 | 0 | size_t count; |
54 | 0 | if (ptls_load_pem_objects(cert_pem_file, "PUBLIC KEY", raw_public_key, 1, &count) != 0) { |
55 | 0 | fprintf(stderr, "failed to load public key:%s:%s\n", cert_pem_file, strerror(errno)); |
56 | 0 | exit(1); |
57 | 0 | } |
58 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:load_raw_public_key Unexecuted instantiation: fuzz-client-hello.c:load_raw_public_key |
59 | | |
60 | | static inline void load_private_key(ptls_context_t *ctx, const char *fn) |
61 | 0 | { |
62 | 0 | static ptls_openssl_sign_certificate_t sc; |
63 | 0 | FILE *fp; |
64 | 0 | EVP_PKEY *pkey; |
65 | 0 |
|
66 | 0 | if ((fp = fopen(fn, "rb")) == NULL) { |
67 | 0 | fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno)); |
68 | 0 | exit(1); |
69 | 0 | } |
70 | 0 | pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL); |
71 | 0 | fclose(fp); |
72 | 0 |
|
73 | 0 | if (pkey == NULL) { |
74 | 0 | fprintf(stderr, "failed to read private key from file:%s\n", fn); |
75 | 0 | exit(1); |
76 | 0 | } |
77 | 0 |
|
78 | 0 | ptls_openssl_init_sign_certificate(&sc, pkey); |
79 | 0 | EVP_PKEY_free(pkey); |
80 | 0 |
|
81 | 0 | ctx->sign_certificate = &sc.super; |
82 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:load_private_key Unexecuted instantiation: fuzz-client-hello.c:load_private_key |
83 | | |
84 | | struct st_util_save_ticket_t { |
85 | | ptls_save_ticket_t super; |
86 | | char fn[MAXPATHLEN]; |
87 | | }; |
88 | | |
89 | | static int util_save_ticket_cb(ptls_save_ticket_t *_self, ptls_t *tls, ptls_iovec_t src) |
90 | 0 | { |
91 | 0 | struct st_util_save_ticket_t *self = (struct st_util_save_ticket_t *)_self; |
92 | 0 | FILE *fp; |
93 | 0 |
|
94 | 0 | if ((fp = fopen(self->fn, "wb")) == NULL) { |
95 | 0 | fprintf(stderr, "failed to open file:%s:%s\n", self->fn, strerror(errno)); |
96 | 0 | return PTLS_ERROR_LIBRARY; |
97 | 0 | } |
98 | 0 | fwrite(src.base, 1, src.len, fp); |
99 | 0 | fclose(fp); |
100 | 0 |
|
101 | 0 | return 0; |
102 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:util_save_ticket_cb Unexecuted instantiation: fuzz-client-hello.c:util_save_ticket_cb |
103 | | |
104 | | static inline void setup_session_file(ptls_context_t *ctx, ptls_handshake_properties_t *hsprop, const char *fn) |
105 | 0 | { |
106 | 0 | static struct st_util_save_ticket_t st; |
107 | 0 | FILE *fp; |
108 | 0 |
|
109 | 0 | /* setup save_ticket callback */ |
110 | 0 | strcpy(st.fn, fn); |
111 | 0 | st.super.cb = util_save_ticket_cb; |
112 | 0 | ctx->save_ticket = &st.super; |
113 | 0 |
|
114 | 0 | /* load session ticket if possible */ |
115 | 0 | if ((fp = fopen(fn, "rb")) != NULL) { |
116 | 0 | static uint8_t ticket[16384]; |
117 | 0 | size_t ticket_size = fread(ticket, 1, sizeof(ticket), fp); |
118 | 0 | if (ticket_size == 0 || !feof(fp)) { |
119 | 0 | fprintf(stderr, "failed to load ticket from file:%s\n", fn); |
120 | 0 | exit(1); |
121 | 0 | } |
122 | 0 | fclose(fp); |
123 | 0 | hsprop->client.session_ticket = ptls_iovec_init(ticket, ticket_size); |
124 | 0 | } |
125 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:setup_session_file Unexecuted instantiation: fuzz-client-hello.c:setup_session_file |
126 | | |
127 | | static inline X509_STORE *init_cert_store(char const *crt_file) |
128 | 0 | { |
129 | 0 | int ret = 0; |
130 | 0 | X509_STORE *store = X509_STORE_new(); |
131 | 0 |
|
132 | 0 | if (store != NULL) { |
133 | 0 | X509_LOOKUP *lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); |
134 | 0 | ret = X509_LOOKUP_load_file(lookup, crt_file, X509_FILETYPE_PEM); |
135 | 0 | if (ret != 1) { |
136 | 0 | fprintf(stderr, "Cannot load store (%s), ret = %d\n", crt_file, ret); |
137 | 0 | X509_STORE_free(store); |
138 | 0 | exit(1); |
139 | 0 | } |
140 | 0 | } else { |
141 | 0 | fprintf(stderr, "Cannot get a new X509 store\n"); |
142 | 0 | exit(1); |
143 | 0 | } |
144 | 0 |
|
145 | 0 | return store; |
146 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:init_cert_store Unexecuted instantiation: fuzz-client-hello.c:init_cert_store |
147 | | |
148 | | static inline void setup_verify_certificate(ptls_context_t *ctx, const char *ca_file) |
149 | 0 | { |
150 | 0 | static ptls_openssl_verify_certificate_t vc; |
151 | 0 | ptls_openssl_init_verify_certificate(&vc, ca_file != NULL ? init_cert_store(ca_file) : NULL); |
152 | 0 | ctx->verify_certificate = &vc.super; |
153 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:setup_verify_certificate Unexecuted instantiation: fuzz-client-hello.c:setup_verify_certificate |
154 | | |
155 | | static inline void setup_raw_pubkey_verify_certificate(ptls_context_t *ctx, EVP_PKEY *pubkey) |
156 | 0 | { |
157 | 0 | static ptls_openssl_raw_pubkey_verify_certificate_t vc; |
158 | 0 | ptls_openssl_raw_pubkey_init_verify_certificate(&vc, pubkey); |
159 | 0 | ctx->verify_certificate = &vc.super; |
160 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:setup_raw_pubkey_verify_certificate Unexecuted instantiation: fuzz-client-hello.c:setup_raw_pubkey_verify_certificate |
161 | | |
162 | | struct st_util_log_event_t { |
163 | | ptls_log_event_t super; |
164 | | FILE *fp; |
165 | | }; |
166 | | |
167 | | static void log_event_cb(ptls_log_event_t *_self, ptls_t *tls, const char *type, const char *fmt, ...) |
168 | 0 | { |
169 | 0 | struct st_util_log_event_t *self = (struct st_util_log_event_t *)_self; |
170 | 0 | char randomhex[PTLS_HELLO_RANDOM_SIZE * 2 + 1]; |
171 | 0 | va_list args; |
172 | 0 |
|
173 | 0 | ptls_hexdump(randomhex, ptls_get_client_random(tls).base, PTLS_HELLO_RANDOM_SIZE); |
174 | 0 | fprintf(self->fp, "%s %s ", type, randomhex); |
175 | 0 |
|
176 | 0 | va_start(args, fmt); |
177 | 0 | vfprintf(self->fp, fmt, args); |
178 | 0 | va_end(args); |
179 | 0 |
|
180 | 0 | fprintf(self->fp, "\n"); |
181 | 0 | fflush(self->fp); |
182 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:log_event_cb Unexecuted instantiation: fuzz-client-hello.c:log_event_cb |
183 | | |
184 | | static inline void setup_log_event(ptls_context_t *ctx, const char *fn) |
185 | 0 | { |
186 | 0 | static struct st_util_log_event_t ls; |
187 | 0 |
|
188 | 0 | if ((ls.fp = fopen(fn, "at")) == NULL) { |
189 | 0 | fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno)); |
190 | 0 | exit(1); |
191 | 0 | } |
192 | 0 | ls.super.cb = log_event_cb; |
193 | 0 | ctx->log_event = &ls.super; |
194 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:setup_log_event Unexecuted instantiation: fuzz-client-hello.c:setup_log_event |
195 | | |
196 | | /* single-entry session cache */ |
197 | | struct st_util_session_cache_t { |
198 | | ptls_encrypt_ticket_t super; |
199 | | uint8_t id[32]; |
200 | | ptls_iovec_t data; |
201 | | }; |
202 | | |
203 | | static int encrypt_ticket_cb(ptls_encrypt_ticket_t *_self, ptls_t *tls, int is_encrypt, ptls_buffer_t *dst, ptls_iovec_t src) |
204 | 0 | { |
205 | 0 | struct st_util_session_cache_t *self = (struct st_util_session_cache_t *)_self; |
206 | 0 | int ret; |
207 | 0 |
|
208 | 0 | if (is_encrypt) { |
209 | 0 |
|
210 | 0 | /* replace the cached entry along with a newly generated session id */ |
211 | 0 | free(self->data.base); |
212 | 0 | if ((self->data.base = (uint8_t *)malloc(src.len)) == NULL) |
213 | 0 | return PTLS_ERROR_NO_MEMORY; |
214 | 0 |
|
215 | 0 | ptls_get_context(tls)->random_bytes(self->id, sizeof(self->id)); |
216 | 0 | memcpy(self->data.base, src.base, src.len); |
217 | 0 | self->data.len = src.len; |
218 | 0 |
|
219 | 0 | /* store the session id in buffer */ |
220 | 0 | if ((ret = ptls_buffer_reserve(dst, sizeof(self->id))) != 0) |
221 | 0 | return ret; |
222 | 0 | memcpy(dst->base + dst->off, self->id, sizeof(self->id)); |
223 | 0 | dst->off += sizeof(self->id); |
224 | 0 |
|
225 | 0 | } else { |
226 | 0 |
|
227 | 0 | /* check if session id is the one stored in cache */ |
228 | 0 | if (src.len != sizeof(self->id)) |
229 | 0 | return PTLS_ERROR_SESSION_NOT_FOUND; |
230 | 0 | if (memcmp(self->id, src.base, sizeof(self->id)) != 0) |
231 | 0 | return PTLS_ERROR_SESSION_NOT_FOUND; |
232 | 0 |
|
233 | 0 | /* return the cached value */ |
234 | 0 | if ((ret = ptls_buffer_reserve(dst, self->data.len)) != 0) |
235 | 0 | return ret; |
236 | 0 | memcpy(dst->base + dst->off, self->data.base, self->data.len); |
237 | 0 | dst->off += self->data.len; |
238 | 0 | } |
239 | 0 |
|
240 | 0 | return 0; |
241 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:encrypt_ticket_cb Unexecuted instantiation: fuzz-client-hello.c:encrypt_ticket_cb |
242 | | |
243 | | static inline void setup_session_cache(ptls_context_t *ctx) |
244 | 0 | { |
245 | 0 | static struct st_util_session_cache_t sc; |
246 | 0 |
|
247 | 0 | sc.super.cb = encrypt_ticket_cb; |
248 | 0 |
|
249 | 0 | ctx->ticket_lifetime = 86400; |
250 | 0 | ctx->max_early_data_size = 8192; |
251 | 0 | ctx->encrypt_ticket = &sc.super; |
252 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:setup_session_cache Unexecuted instantiation: fuzz-client-hello.c:setup_session_cache |
253 | | |
254 | | static struct { |
255 | | ptls_iovec_t config_list; |
256 | | struct { |
257 | | struct { |
258 | | ptls_hpke_kem_t *kem; |
259 | | ptls_key_exchange_context_t *ctx; |
260 | | } list[16]; |
261 | | size_t count; |
262 | | } keyex; |
263 | | struct { |
264 | | ptls_iovec_t configs; |
265 | | char *fn; |
266 | | } retry; |
267 | | } ech; |
268 | | |
269 | | static ptls_aead_context_t *ech_create_opener(ptls_ech_create_opener_t *self, ptls_hpke_kem_t **kem, |
270 | | ptls_hpke_cipher_suite_t **cipher, ptls_t *tls, uint8_t config_id, |
271 | | ptls_hpke_cipher_suite_id_t cipher_id, ptls_iovec_t enc, ptls_iovec_t info_prefix) |
272 | 0 | { |
273 | 0 | const uint8_t *src = ech.config_list.base, *const end = src + ech.config_list.len; |
274 | 0 | size_t index = 0; |
275 | 0 | int ret = 0; |
276 | 0 |
|
277 | 0 | /* look for the cipher implementation; this should better be specific to each ECHConfig (as each of them may advertise different |
278 | 0 | * set of values) */ |
279 | 0 | *cipher = NULL; |
280 | 0 | for (size_t i = 0; ptls_openssl_hpke_cipher_suites[i] != NULL; ++i) { |
281 | 0 | if (ptls_openssl_hpke_cipher_suites[i]->id.kdf == cipher_id.kdf && |
282 | 0 | ptls_openssl_hpke_cipher_suites[i]->id.aead == cipher_id.aead) { |
283 | 0 | *cipher = ptls_openssl_hpke_cipher_suites[i]; |
284 | 0 | break; |
285 | 0 | } |
286 | 0 | } |
287 | 0 | if (*cipher == NULL) |
288 | 0 | goto Exit; |
289 | 0 |
|
290 | 0 | ptls_decode_open_block(src, end, 2, { |
291 | 0 | uint16_t version; |
292 | 0 | if ((ret = ptls_decode16(&version, &src, end)) != 0) |
293 | 0 | goto Exit; |
294 | 0 | do { |
295 | 0 | ptls_decode_open_block(src, end, 2, { |
296 | 0 | if (src == end) { |
297 | 0 | ret = PTLS_ALERT_DECODE_ERROR; |
298 | 0 | goto Exit; |
299 | 0 | } |
300 | 0 | if (*src == config_id) { |
301 | 0 | /* this is the ECHConfig that we have been looking for */ |
302 | 0 | if (index >= ech.keyex.count) { |
303 | 0 | fprintf(stderr, "ECH key missing for config %zu\n", index); |
304 | 0 | return NULL; |
305 | 0 | } |
306 | 0 | uint8_t *info = malloc(info_prefix.len + end - (src - 4)); |
307 | 0 | memcpy(info, info_prefix.base, info_prefix.len); |
308 | 0 | memcpy(info + info_prefix.len, src - 4, end - (src - 4)); |
309 | 0 | ptls_aead_context_t *aead; |
310 | 0 | ptls_hpke_setup_base_r(ech.keyex.list[index].kem, *cipher, ech.keyex.list[index].ctx, &aead, enc, |
311 | 0 | ptls_iovec_init(info, info_prefix.len + end - (src - 4))); |
312 | 0 | free(info); |
313 | 0 | *kem = ech.keyex.list[index].kem; |
314 | 0 | return aead; |
315 | 0 | } |
316 | 0 | ++index; |
317 | 0 | src = end; |
318 | 0 | }); |
319 | 0 | } while (src != end); |
320 | 0 | }); |
321 | 0 |
|
322 | 0 | Exit: |
323 | 0 | if (ret != 0) |
324 | 0 | fprintf(stderr, "ECH decode error:%d\n", ret); |
325 | 0 | return NULL; |
326 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:ech_create_opener Unexecuted instantiation: fuzz-client-hello.c:ech_create_opener |
327 | | |
328 | | static void ech_save_retry_configs(void) |
329 | 0 | { |
330 | 0 | if (ech.retry.configs.base == NULL) |
331 | 0 | return; |
332 | 0 |
|
333 | 0 | FILE *fp; |
334 | 0 | if ((fp = fopen(ech.retry.fn, "wt")) == NULL) { |
335 | 0 | fprintf(stderr, "failed to write to ECH config file:%s:%s\n", ech.retry.fn, strerror(errno)); |
336 | 0 | exit(1); |
337 | 0 | } |
338 | 0 | fwrite(ech.retry.configs.base, 1, ech.retry.configs.len, fp); |
339 | 0 | fclose(fp); |
340 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:ech_save_retry_configs Unexecuted instantiation: fuzz-client-hello.c:ech_save_retry_configs |
341 | | |
342 | | static ptls_iovec_t load_file(const char *fn) |
343 | 0 | { |
344 | 0 | FILE *fp; |
345 | 0 | ptls_iovec_t buf; |
346 | 0 |
|
347 | 0 | if ((fp = fopen(fn, "rt")) == NULL) { |
348 | 0 | fprintf(stderr, "failed to open file:%s:%s\n", fn, strerror(errno)); |
349 | 0 | exit(1); |
350 | 0 | } |
351 | 0 | buf.len = 65536; |
352 | 0 | if ((buf.base = malloc(buf.len)) == NULL) { |
353 | 0 | fprintf(stderr, "no memory\n"); |
354 | 0 | abort(); |
355 | 0 | } |
356 | 0 | buf.len = fread(buf.base, 1, buf.len, fp); |
357 | 0 | fclose(fp); |
358 | 0 |
|
359 | 0 | return buf; |
360 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:load_file Unexecuted instantiation: fuzz-client-hello.c:load_file |
361 | | |
362 | | static void ech_setup_configs(const char *fn) |
363 | 0 | { |
364 | 0 | ech.config_list = load_file(fn); |
365 | 0 | ech.retry.fn = strdup(fn); |
366 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:ech_setup_configs Unexecuted instantiation: fuzz-client-hello.c:ech_setup_configs |
367 | | |
368 | | static void ech_setup_key(ptls_context_t *ctx, const char *fn) |
369 | 0 | { |
370 | 0 | FILE *fp; |
371 | 0 | EVP_PKEY *pkey; |
372 | 0 | int ret; |
373 | 0 |
|
374 | 0 | if ((fp = fopen(fn, "rt")) == NULL) { |
375 | 0 | fprintf(stderr, "failed to open ECH private key file:%s:%s\n", fn, strerror(errno)); |
376 | 0 | exit(1); |
377 | 0 | } |
378 | 0 | if ((pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL)) == NULL) { |
379 | 0 | fprintf(stderr, "failed to load private key from file:%s\n", fn); |
380 | 0 | exit(1); |
381 | 0 | } |
382 | 0 | if ((ret = ptls_openssl_create_key_exchange(&ech.keyex.list[ech.keyex.count].ctx, pkey)) != 0) { |
383 | 0 | fprintf(stderr, "failed to load private key from file:%s:picotls-error:%d", fn, ret); |
384 | 0 | exit(1); |
385 | 0 | } |
386 | 0 | EVP_PKEY_free(pkey); |
387 | 0 | fclose(fp); |
388 | 0 |
|
389 | 0 | for (size_t i = 0; ptls_openssl_hpke_kems[i] != NULL; ++i) { |
390 | 0 | if (ptls_openssl_hpke_kems[i]->keyex == ech.keyex.list[ech.keyex.count].ctx->algo) { |
391 | 0 | ech.keyex.list[ech.keyex.count].kem = ptls_openssl_hpke_kems[i]; |
392 | 0 | break; |
393 | 0 | } |
394 | 0 | } |
395 | 0 | if (ech.keyex.list[ech.keyex.count].kem == NULL) { |
396 | 0 | fprintf(stderr, "kem unknown for private key:%s\n", fn); |
397 | 0 | exit(1); |
398 | 0 | } |
399 | 0 |
|
400 | 0 | ++ech.keyex.count; |
401 | 0 |
|
402 | 0 | static ptls_ech_create_opener_t opener = {.cb = ech_create_opener}; |
403 | 0 | ctx->ech.server.create_opener = &opener; |
404 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:ech_setup_key Unexecuted instantiation: fuzz-client-hello.c:ech_setup_key |
405 | | |
406 | | static inline int resolve_address(struct sockaddr *sa, socklen_t *salen, const char *host, const char *port, int family, int type, |
407 | | int proto) |
408 | 0 | { |
409 | 0 | struct addrinfo hints, *res; |
410 | 0 | int err; |
411 | 0 |
|
412 | 0 | memset(&hints, 0, sizeof(hints)); |
413 | 0 | hints.ai_family = family; |
414 | 0 | hints.ai_socktype = type; |
415 | 0 | hints.ai_protocol = proto; |
416 | 0 | hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV | AI_PASSIVE; |
417 | 0 | if ((err = getaddrinfo(host, port, &hints, &res)) != 0 || res == NULL) { |
418 | 0 | fprintf(stderr, "failed to resolve address:%s:%s:%s\n", host, port, |
419 | 0 | err != 0 ? gai_strerror(err) : "getaddrinfo returned NULL"); |
420 | 0 | return -1; |
421 | 0 | } |
422 | 0 |
|
423 | 0 | memcpy(sa, res->ai_addr, res->ai_addrlen); |
424 | 0 | *salen = res->ai_addrlen; |
425 | 0 |
|
426 | 0 | freeaddrinfo(res); |
427 | 0 | return 0; |
428 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:resolve_address Unexecuted instantiation: fuzz-client-hello.c:resolve_address |
429 | | |
430 | | static inline int normalize_txt(uint8_t *p, size_t len) |
431 | 0 | { |
432 | 0 | uint8_t *const end = p + len, *dst = p; |
433 | 0 |
|
434 | 0 | if (p == end) |
435 | 0 | return 0; |
436 | 0 |
|
437 | 0 | do { |
438 | 0 | size_t block_len = *p++; |
439 | 0 | if (end - p < block_len) |
440 | 0 | return 0; |
441 | 0 | memmove(dst, p, block_len); |
442 | 0 | dst += block_len; |
443 | 0 | p += block_len; |
444 | 0 | } while (p != end); |
445 | 0 | *dst = '\0'; |
446 | 0 |
|
447 | 0 | return 1; |
448 | 0 | } Unexecuted instantiation: fuzz-server-hello.c:normalize_txt Unexecuted instantiation: fuzz-client-hello.c:normalize_txt |
449 | | |
450 | | /* The ptls_repeat_while_eintr macro will repeat a function call (block) if it is interrupted (EINTR) before completion. If failing |
451 | | * for other reason, the macro executes the exit block, such as either { break; } or { goto Fail; }. |
452 | | */ |
453 | | #ifdef _WINDOWS |
454 | | #define repeat_while_eintr(expr, exit_block) \ |
455 | | while ((expr) < 0) { \ |
456 | | exit_block; \ |
457 | | } |
458 | | #else |
459 | | #define repeat_while_eintr(expr, exit_block) \ |
460 | | while ((expr) < 0) { \ |
461 | | if (errno == EINTR) \ |
462 | | continue; \ |
463 | | exit_block; \ |
464 | | } |
465 | | #endif |
466 | | |
467 | | #endif |