Line data Source code
1 : /* cell_common.c -- generated by Trunnel v1.5.3.
2 : * https://gitweb.torproject.org/trunnel.git
3 : * You probably shouldn't edit this file.
4 : */
5 : #include <stdlib.h>
6 : #include "trunnel-impl.h"
7 :
8 : #include "cell_common.h"
9 :
10 : #define TRUNNEL_SET_ERROR_CODE(obj) \
11 : do { \
12 : (obj)->trunnel_error_code_ = 1; \
13 : } while (0)
14 :
15 : #if defined(__COVERITY__) || defined(__clang_analyzer__)
16 : /* If we're running a static analysis tool, we don't want it to complain
17 : * that some of our remaining-bytes checks are dead-code. */
18 : int cellcommon_deadcode_dummy__ = 0;
19 : #define OR_DEADCODE_DUMMY || cellcommon_deadcode_dummy__
20 : #else
21 : #define OR_DEADCODE_DUMMY
22 : #endif
23 :
24 : #define CHECK_REMAINING(nbytes, label) \
25 : do { \
26 : if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 : goto label; \
28 : } \
29 : } while (0)
30 :
31 : trn_cell_extension_field_t *
32 12 : trn_cell_extension_field_new(void)
33 : {
34 12 : trn_cell_extension_field_t *val = trunnel_calloc(1, sizeof(trn_cell_extension_field_t));
35 12 : if (NULL == val)
36 0 : return NULL;
37 : return val;
38 : }
39 :
40 : /** Release all storage held inside 'obj', but do not free 'obj'.
41 : */
42 : static void
43 12 : trn_cell_extension_field_clear(trn_cell_extension_field_t *obj)
44 : {
45 12 : (void) obj;
46 12 : TRUNNEL_DYNARRAY_WIPE(&obj->field);
47 12 : TRUNNEL_DYNARRAY_CLEAR(&obj->field);
48 12 : }
49 :
50 : void
51 12 : trn_cell_extension_field_free(trn_cell_extension_field_t *obj)
52 : {
53 12 : if (obj == NULL)
54 : return;
55 12 : trn_cell_extension_field_clear(obj);
56 12 : trunnel_memwipe(obj, sizeof(trn_cell_extension_field_t));
57 12 : trunnel_free_(obj);
58 : }
59 :
60 : uint8_t
61 7 : trn_cell_extension_field_get_field_type(const trn_cell_extension_field_t *inp)
62 : {
63 7 : return inp->field_type;
64 : }
65 : int
66 7 : trn_cell_extension_field_set_field_type(trn_cell_extension_field_t *inp, uint8_t val)
67 : {
68 7 : inp->field_type = val;
69 7 : return 0;
70 : }
71 : uint8_t
72 0 : trn_cell_extension_field_get_field_len(const trn_cell_extension_field_t *inp)
73 : {
74 0 : return inp->field_len;
75 : }
76 : int
77 7 : trn_cell_extension_field_set_field_len(trn_cell_extension_field_t *inp, uint8_t val)
78 : {
79 7 : inp->field_len = val;
80 7 : return 0;
81 : }
82 : size_t
83 14 : trn_cell_extension_field_getlen_field(const trn_cell_extension_field_t *inp)
84 : {
85 14 : return TRUNNEL_DYNARRAY_LEN(&inp->field);
86 : }
87 :
88 : uint8_t
89 0 : trn_cell_extension_field_get_field(trn_cell_extension_field_t *inp, size_t idx)
90 : {
91 0 : return TRUNNEL_DYNARRAY_GET(&inp->field, idx);
92 : }
93 :
94 : uint8_t
95 0 : trn_cell_extension_field_getconst_field(const trn_cell_extension_field_t *inp, size_t idx)
96 : {
97 0 : return trn_cell_extension_field_get_field((trn_cell_extension_field_t*)inp, idx);
98 : }
99 : int
100 0 : trn_cell_extension_field_set_field(trn_cell_extension_field_t *inp, size_t idx, uint8_t elt)
101 : {
102 0 : TRUNNEL_DYNARRAY_SET(&inp->field, idx, elt);
103 0 : return 0;
104 : }
105 : int
106 0 : trn_cell_extension_field_add_field(trn_cell_extension_field_t *inp, uint8_t elt)
107 : {
108 : #if SIZE_MAX >= UINT8_MAX
109 0 : if (inp->field.n_ == UINT8_MAX)
110 0 : goto trunnel_alloc_failed;
111 : #endif
112 0 : TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->field, elt, {});
113 0 : return 0;
114 0 : trunnel_alloc_failed:
115 0 : TRUNNEL_SET_ERROR_CODE(inp);
116 0 : return -1;
117 : }
118 :
119 : uint8_t *
120 14 : trn_cell_extension_field_getarray_field(trn_cell_extension_field_t *inp)
121 : {
122 14 : return inp->field.elts_;
123 : }
124 : const uint8_t *
125 7 : trn_cell_extension_field_getconstarray_field(const trn_cell_extension_field_t *inp)
126 : {
127 7 : return (const uint8_t *)trn_cell_extension_field_getarray_field((trn_cell_extension_field_t*)inp);
128 : }
129 : int
130 7 : trn_cell_extension_field_setlen_field(trn_cell_extension_field_t *inp, size_t newlen)
131 : {
132 7 : uint8_t *newptr;
133 : #if UINT8_MAX < SIZE_MAX
134 7 : if (newlen > UINT8_MAX)
135 0 : goto trunnel_alloc_failed;
136 : #endif
137 14 : newptr = trunnel_dynarray_setlen(&inp->field.allocated_,
138 7 : &inp->field.n_, inp->field.elts_, newlen,
139 : sizeof(inp->field.elts_[0]), (trunnel_free_fn_t) NULL,
140 : &inp->trunnel_error_code_);
141 7 : if (newlen != 0 && newptr == NULL)
142 0 : goto trunnel_alloc_failed;
143 7 : inp->field.elts_ = newptr;
144 7 : return 0;
145 0 : trunnel_alloc_failed:
146 0 : TRUNNEL_SET_ERROR_CODE(inp);
147 0 : return -1;
148 : }
149 : const char *
150 45 : trn_cell_extension_field_check(const trn_cell_extension_field_t *obj)
151 : {
152 45 : if (obj == NULL)
153 : return "Object was NULL";
154 45 : if (obj->trunnel_error_code_)
155 : return "A set function failed on this object";
156 45 : if (TRUNNEL_DYNARRAY_LEN(&obj->field) != obj->field_len)
157 0 : return "Length mismatch for field";
158 : return NULL;
159 : }
160 :
161 : ssize_t
162 0 : trn_cell_extension_field_encoded_len(const trn_cell_extension_field_t *obj)
163 : {
164 0 : ssize_t result = 0;
165 :
166 0 : if (NULL != trn_cell_extension_field_check(obj))
167 : return -1;
168 :
169 :
170 : /* Length of u8 field_type */
171 0 : result += 1;
172 :
173 : /* Length of u8 field_len */
174 0 : result += 1;
175 :
176 : /* Length of u8 field[field_len] */
177 0 : result += TRUNNEL_DYNARRAY_LEN(&obj->field);
178 0 : return result;
179 : }
180 : int
181 0 : trn_cell_extension_field_clear_errors(trn_cell_extension_field_t *obj)
182 : {
183 0 : int r = obj->trunnel_error_code_;
184 0 : obj->trunnel_error_code_ = 0;
185 0 : return r;
186 : }
187 : ssize_t
188 15 : trn_cell_extension_field_encode(uint8_t *output, const size_t avail, const trn_cell_extension_field_t *obj)
189 : {
190 15 : ssize_t result = 0;
191 15 : size_t written = 0;
192 15 : uint8_t *ptr = output;
193 15 : const char *msg;
194 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 : const ssize_t encoded_len = trn_cell_extension_field_encoded_len(obj);
196 : #endif
197 :
198 15 : if (NULL != (msg = trn_cell_extension_field_check(obj)))
199 0 : goto check_failed;
200 :
201 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 : trunnel_assert(encoded_len >= 0);
203 : #endif
204 :
205 : /* Encode u8 field_type */
206 15 : trunnel_assert(written <= avail);
207 15 : if (avail - written < 1)
208 0 : goto truncated;
209 15 : trunnel_set_uint8(ptr, (obj->field_type));
210 15 : written += 1; ptr += 1;
211 :
212 : /* Encode u8 field_len */
213 15 : trunnel_assert(written <= avail);
214 15 : if (avail - written < 1)
215 0 : goto truncated;
216 15 : trunnel_set_uint8(ptr, (obj->field_len));
217 15 : written += 1; ptr += 1;
218 :
219 : /* Encode u8 field[field_len] */
220 : {
221 15 : size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->field);
222 15 : trunnel_assert(obj->field_len == elt_len);
223 15 : trunnel_assert(written <= avail);
224 15 : if (avail - written < elt_len)
225 0 : goto truncated;
226 15 : if (elt_len)
227 15 : memcpy(ptr, obj->field.elts_, elt_len);
228 15 : written += elt_len; ptr += elt_len;
229 : }
230 :
231 :
232 15 : trunnel_assert(ptr == output + written);
233 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
234 : {
235 : trunnel_assert(encoded_len >= 0);
236 : trunnel_assert((size_t)encoded_len == written);
237 : }
238 :
239 : #endif
240 :
241 15 : return written;
242 :
243 0 : truncated:
244 0 : result = -2;
245 0 : goto fail;
246 0 : check_failed:
247 0 : (void)msg;
248 0 : result = -1;
249 0 : goto fail;
250 : fail:
251 : trunnel_assert(result < 0);
252 : return result;
253 : }
254 :
255 : /** As trn_cell_extension_field_parse(), but do not allocate the
256 : * output object.
257 : */
258 : static ssize_t
259 5 : trn_cell_extension_field_parse_into(trn_cell_extension_field_t *obj, const uint8_t *input, const size_t len_in)
260 : {
261 5 : const uint8_t *ptr = input;
262 5 : size_t remaining = len_in;
263 5 : ssize_t result = 0;
264 5 : (void)result;
265 :
266 : /* Parse u8 field_type */
267 5 : CHECK_REMAINING(1, truncated);
268 5 : obj->field_type = (trunnel_get_uint8(ptr));
269 5 : remaining -= 1; ptr += 1;
270 :
271 : /* Parse u8 field_len */
272 5 : CHECK_REMAINING(1, truncated);
273 5 : obj->field_len = (trunnel_get_uint8(ptr));
274 5 : remaining -= 1; ptr += 1;
275 :
276 : /* Parse u8 field[field_len] */
277 5 : CHECK_REMAINING(obj->field_len, truncated);
278 5 : TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->field, obj->field_len, {});
279 5 : obj->field.n_ = obj->field_len;
280 5 : if (obj->field_len)
281 5 : memcpy(obj->field.elts_, ptr, obj->field_len);
282 5 : ptr += obj->field_len; remaining -= obj->field_len;
283 5 : trunnel_assert(ptr + remaining == input + len_in);
284 5 : return len_in - remaining;
285 :
286 : truncated:
287 : return -2;
288 0 : trunnel_alloc_failed:
289 0 : return -1;
290 : }
291 :
292 : ssize_t
293 5 : trn_cell_extension_field_parse(trn_cell_extension_field_t **output, const uint8_t *input, const size_t len_in)
294 : {
295 5 : ssize_t result;
296 5 : *output = trn_cell_extension_field_new();
297 5 : if (NULL == *output)
298 : return -1;
299 5 : result = trn_cell_extension_field_parse_into(*output, input, len_in);
300 5 : if (result < 0) {
301 0 : trn_cell_extension_field_free(*output);
302 0 : *output = NULL;
303 : }
304 : return result;
305 : }
306 : trn_cell_extension_t *
307 65 : trn_cell_extension_new(void)
308 : {
309 65 : trn_cell_extension_t *val = trunnel_calloc(1, sizeof(trn_cell_extension_t));
310 65 : if (NULL == val)
311 0 : return NULL;
312 : return val;
313 : }
314 :
315 : /** Release all storage held inside 'obj', but do not free 'obj'.
316 : */
317 : static void
318 65 : trn_cell_extension_clear(trn_cell_extension_t *obj)
319 : {
320 65 : (void) obj;
321 : {
322 :
323 65 : unsigned idx;
324 77 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
325 12 : trn_cell_extension_field_free(TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
326 : }
327 : }
328 65 : TRUNNEL_DYNARRAY_WIPE(&obj->fields);
329 65 : TRUNNEL_DYNARRAY_CLEAR(&obj->fields);
330 65 : }
331 :
332 : void
333 68 : trn_cell_extension_free(trn_cell_extension_t *obj)
334 : {
335 68 : if (obj == NULL)
336 : return;
337 65 : trn_cell_extension_clear(obj);
338 65 : trunnel_memwipe(obj, sizeof(trn_cell_extension_t));
339 65 : trunnel_free_(obj);
340 : }
341 :
342 : uint8_t
343 21 : trn_cell_extension_get_num(const trn_cell_extension_t *inp)
344 : {
345 21 : return inp->num;
346 : }
347 : int
348 42 : trn_cell_extension_set_num(trn_cell_extension_t *inp, uint8_t val)
349 : {
350 42 : inp->num = val;
351 42 : return 0;
352 : }
353 : size_t
354 0 : trn_cell_extension_getlen_fields(const trn_cell_extension_t *inp)
355 : {
356 0 : return TRUNNEL_DYNARRAY_LEN(&inp->fields);
357 : }
358 :
359 : struct trn_cell_extension_field_st *
360 7 : trn_cell_extension_get_fields(trn_cell_extension_t *inp, size_t idx)
361 : {
362 7 : return TRUNNEL_DYNARRAY_GET(&inp->fields, idx);
363 : }
364 :
365 : const struct trn_cell_extension_field_st *
366 7 : trn_cell_extension_getconst_fields(const trn_cell_extension_t *inp, size_t idx)
367 : {
368 7 : return trn_cell_extension_get_fields((trn_cell_extension_t*)inp, idx);
369 : }
370 : int
371 0 : trn_cell_extension_set_fields(trn_cell_extension_t *inp, size_t idx, struct trn_cell_extension_field_st * elt)
372 : {
373 0 : trn_cell_extension_field_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->fields, idx);
374 0 : if (oldval && oldval != elt)
375 0 : trn_cell_extension_field_free(oldval);
376 0 : return trn_cell_extension_set0_fields(inp, idx, elt);
377 : }
378 : int
379 0 : trn_cell_extension_set0_fields(trn_cell_extension_t *inp, size_t idx, struct trn_cell_extension_field_st * elt)
380 : {
381 0 : TRUNNEL_DYNARRAY_SET(&inp->fields, idx, elt);
382 0 : return 0;
383 : }
384 : int
385 7 : trn_cell_extension_add_fields(trn_cell_extension_t *inp, struct trn_cell_extension_field_st * elt)
386 : {
387 : #if SIZE_MAX >= UINT8_MAX
388 7 : if (inp->fields.n_ == UINT8_MAX)
389 0 : goto trunnel_alloc_failed;
390 : #endif
391 7 : TRUNNEL_DYNARRAY_ADD(struct trn_cell_extension_field_st *, &inp->fields, elt, {});
392 7 : return 0;
393 0 : trunnel_alloc_failed:
394 0 : TRUNNEL_SET_ERROR_CODE(inp);
395 0 : return -1;
396 : }
397 :
398 : struct trn_cell_extension_field_st * *
399 0 : trn_cell_extension_getarray_fields(trn_cell_extension_t *inp)
400 : {
401 0 : return inp->fields.elts_;
402 : }
403 : const struct trn_cell_extension_field_st * const *
404 0 : trn_cell_extension_getconstarray_fields(const trn_cell_extension_t *inp)
405 : {
406 0 : return (const struct trn_cell_extension_field_st * const *)trn_cell_extension_getarray_fields((trn_cell_extension_t*)inp);
407 : }
408 : int
409 0 : trn_cell_extension_setlen_fields(trn_cell_extension_t *inp, size_t newlen)
410 : {
411 0 : struct trn_cell_extension_field_st * *newptr;
412 : #if UINT8_MAX < SIZE_MAX
413 0 : if (newlen > UINT8_MAX)
414 0 : goto trunnel_alloc_failed;
415 : #endif
416 0 : newptr = trunnel_dynarray_setlen(&inp->fields.allocated_,
417 0 : &inp->fields.n_, inp->fields.elts_, newlen,
418 : sizeof(inp->fields.elts_[0]), (trunnel_free_fn_t) trn_cell_extension_field_free,
419 : &inp->trunnel_error_code_);
420 0 : if (newlen != 0 && newptr == NULL)
421 0 : goto trunnel_alloc_failed;
422 0 : inp->fields.elts_ = newptr;
423 0 : return 0;
424 0 : trunnel_alloc_failed:
425 0 : TRUNNEL_SET_ERROR_CODE(inp);
426 0 : return -1;
427 : }
428 : const char *
429 170 : trn_cell_extension_check(const trn_cell_extension_t *obj)
430 : {
431 170 : if (obj == NULL)
432 : return "Object was NULL";
433 170 : if (obj->trunnel_error_code_)
434 : return "A set function failed on this object";
435 : {
436 : const char *msg;
437 :
438 : unsigned idx;
439 200 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
440 30 : if (NULL != (msg = trn_cell_extension_field_check(TRUNNEL_DYNARRAY_GET(&obj->fields, idx))))
441 0 : return msg;
442 : }
443 : }
444 170 : if (TRUNNEL_DYNARRAY_LEN(&obj->fields) != obj->num)
445 0 : return "Length mismatch for fields";
446 : return NULL;
447 : }
448 :
449 : ssize_t
450 16 : trn_cell_extension_encoded_len(const trn_cell_extension_t *obj)
451 : {
452 16 : ssize_t result = 0;
453 :
454 16 : if (NULL != trn_cell_extension_check(obj))
455 : return -1;
456 :
457 :
458 : /* Length of u8 num */
459 : result += 1;
460 :
461 : /* Length of struct trn_cell_extension_field fields[num] */
462 : {
463 :
464 : unsigned idx;
465 16 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
466 0 : result += trn_cell_extension_field_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
467 : }
468 : }
469 : return result;
470 : }
471 : int
472 0 : trn_cell_extension_clear_errors(trn_cell_extension_t *obj)
473 : {
474 0 : int r = obj->trunnel_error_code_;
475 0 : obj->trunnel_error_code_ = 0;
476 0 : return r;
477 : }
478 : ssize_t
479 69 : trn_cell_extension_encode(uint8_t *output, const size_t avail, const trn_cell_extension_t *obj)
480 : {
481 69 : ssize_t result = 0;
482 69 : size_t written = 0;
483 69 : uint8_t *ptr = output;
484 69 : const char *msg;
485 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
486 : const ssize_t encoded_len = trn_cell_extension_encoded_len(obj);
487 : #endif
488 :
489 69 : if (NULL != (msg = trn_cell_extension_check(obj)))
490 0 : goto check_failed;
491 :
492 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
493 : trunnel_assert(encoded_len >= 0);
494 : #endif
495 :
496 : /* Encode u8 num */
497 69 : trunnel_assert(written <= avail);
498 69 : if (avail - written < 1)
499 0 : goto truncated;
500 69 : trunnel_set_uint8(ptr, (obj->num));
501 69 : written += 1; ptr += 1;
502 :
503 : /* Encode struct trn_cell_extension_field fields[num] */
504 : {
505 :
506 69 : unsigned idx;
507 84 : for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
508 15 : trunnel_assert(written <= avail);
509 15 : result = trn_cell_extension_field_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
510 15 : if (result < 0)
511 0 : goto fail; /* XXXXXXX !*/
512 15 : written += result; ptr += result;
513 : }
514 : }
515 :
516 :
517 69 : trunnel_assert(ptr == output + written);
518 : #ifdef TRUNNEL_CHECK_ENCODED_LEN
519 : {
520 : trunnel_assert(encoded_len >= 0);
521 : trunnel_assert((size_t)encoded_len == written);
522 : }
523 :
524 : #endif
525 :
526 69 : return written;
527 :
528 0 : truncated:
529 0 : result = -2;
530 0 : goto fail;
531 0 : check_failed:
532 0 : (void)msg;
533 0 : result = -1;
534 0 : goto fail;
535 0 : fail:
536 0 : trunnel_assert(result < 0);
537 : return result;
538 : }
539 :
540 : /** As trn_cell_extension_parse(), but do not allocate the output
541 : * object.
542 : */
543 : static ssize_t
544 30 : trn_cell_extension_parse_into(trn_cell_extension_t *obj, const uint8_t *input, const size_t len_in)
545 : {
546 30 : const uint8_t *ptr = input;
547 30 : size_t remaining = len_in;
548 30 : ssize_t result = 0;
549 30 : (void)result;
550 :
551 : /* Parse u8 num */
552 30 : CHECK_REMAINING(1, truncated);
553 30 : obj->num = (trunnel_get_uint8(ptr));
554 30 : remaining -= 1; ptr += 1;
555 :
556 : /* Parse struct trn_cell_extension_field fields[num] */
557 30 : TRUNNEL_DYNARRAY_EXPAND(trn_cell_extension_field_t *, &obj->fields, obj->num, {});
558 : {
559 30 : trn_cell_extension_field_t * elt;
560 30 : unsigned idx;
561 35 : for (idx = 0; idx < obj->num; ++idx) {
562 5 : result = trn_cell_extension_field_parse(&elt, ptr, remaining);
563 5 : if (result < 0)
564 0 : goto relay_fail;
565 5 : trunnel_assert((size_t)result <= remaining);
566 5 : remaining -= result; ptr += result;
567 5 : TRUNNEL_DYNARRAY_ADD(trn_cell_extension_field_t *, &obj->fields, elt, {trn_cell_extension_field_free(elt);});
568 : }
569 : }
570 30 : trunnel_assert(ptr + remaining == input + len_in);
571 30 : return len_in - remaining;
572 :
573 0 : truncated:
574 0 : return -2;
575 0 : relay_fail:
576 0 : trunnel_assert(result < 0);
577 : return result;
578 : trunnel_alloc_failed:
579 : return -1;
580 : }
581 :
582 : ssize_t
583 30 : trn_cell_extension_parse(trn_cell_extension_t **output, const uint8_t *input, const size_t len_in)
584 : {
585 30 : ssize_t result;
586 30 : *output = trn_cell_extension_new();
587 30 : if (NULL == *output)
588 : return -1;
589 30 : result = trn_cell_extension_parse_into(*output, input, len_in);
590 30 : if (result < 0) {
591 0 : trn_cell_extension_free(*output);
592 0 : *output = NULL;
593 : }
594 : return result;
595 : }
|