Merge remote-tracking branch 'mbeth-private/ticket40821_mr'
[tor.git] / src / trunnel / extension.c
blob538ac62928cddac0e61f6a0c305e118b225b57dc
1 /* extension.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"
8 #include "extension.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
11 do { \
12 (obj)->trunnel_error_code_ = 1; \
13 } while (0)
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 extension_deadcode_dummy__ = 0;
19 #define OR_DEADCODE_DUMMY || extension_deadcode_dummy__
20 #else
21 #define OR_DEADCODE_DUMMY
22 #endif
24 #define CHECK_REMAINING(nbytes, label) \
25 do { \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
27 goto label; \
28 } \
29 } while (0)
31 trn_extension_field_t *
32 trn_extension_field_new(void)
34 trn_extension_field_t *val = trunnel_calloc(1, sizeof(trn_extension_field_t));
35 if (NULL == val)
36 return NULL;
37 return val;
40 /** Release all storage held inside 'obj', but do not free 'obj'.
42 static void
43 trn_extension_field_clear(trn_extension_field_t *obj)
45 (void) obj;
46 TRUNNEL_DYNARRAY_WIPE(&obj->field);
47 TRUNNEL_DYNARRAY_CLEAR(&obj->field);
50 void
51 trn_extension_field_free(trn_extension_field_t *obj)
53 if (obj == NULL)
54 return;
55 trn_extension_field_clear(obj);
56 trunnel_memwipe(obj, sizeof(trn_extension_field_t));
57 trunnel_free_(obj);
60 uint8_t
61 trn_extension_field_get_field_type(const trn_extension_field_t *inp)
63 return inp->field_type;
65 int
66 trn_extension_field_set_field_type(trn_extension_field_t *inp, uint8_t val)
68 inp->field_type = val;
69 return 0;
71 uint8_t
72 trn_extension_field_get_field_len(const trn_extension_field_t *inp)
74 return inp->field_len;
76 int
77 trn_extension_field_set_field_len(trn_extension_field_t *inp, uint8_t val)
79 inp->field_len = val;
80 return 0;
82 size_t
83 trn_extension_field_getlen_field(const trn_extension_field_t *inp)
85 return TRUNNEL_DYNARRAY_LEN(&inp->field);
88 uint8_t
89 trn_extension_field_get_field(trn_extension_field_t *inp, size_t idx)
91 return TRUNNEL_DYNARRAY_GET(&inp->field, idx);
94 uint8_t
95 trn_extension_field_getconst_field(const trn_extension_field_t *inp, size_t idx)
97 return trn_extension_field_get_field((trn_extension_field_t*)inp, idx);
99 int
100 trn_extension_field_set_field(trn_extension_field_t *inp, size_t idx, uint8_t elt)
102 TRUNNEL_DYNARRAY_SET(&inp->field, idx, elt);
103 return 0;
106 trn_extension_field_add_field(trn_extension_field_t *inp, uint8_t elt)
108 #if SIZE_MAX >= UINT8_MAX
109 if (inp->field.n_ == UINT8_MAX)
110 goto trunnel_alloc_failed;
111 #endif
112 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp->field, elt, {});
113 return 0;
114 trunnel_alloc_failed:
115 TRUNNEL_SET_ERROR_CODE(inp);
116 return -1;
119 uint8_t *
120 trn_extension_field_getarray_field(trn_extension_field_t *inp)
122 return inp->field.elts_;
124 const uint8_t *
125 trn_extension_field_getconstarray_field(const trn_extension_field_t *inp)
127 return (const uint8_t *)trn_extension_field_getarray_field((trn_extension_field_t*)inp);
130 trn_extension_field_setlen_field(trn_extension_field_t *inp, size_t newlen)
132 uint8_t *newptr;
133 #if UINT8_MAX < SIZE_MAX
134 if (newlen > UINT8_MAX)
135 goto trunnel_alloc_failed;
136 #endif
137 newptr = trunnel_dynarray_setlen(&inp->field.allocated_,
138 &inp->field.n_, inp->field.elts_, newlen,
139 sizeof(inp->field.elts_[0]), (trunnel_free_fn_t) NULL,
140 &inp->trunnel_error_code_);
141 if (newlen != 0 && newptr == NULL)
142 goto trunnel_alloc_failed;
143 inp->field.elts_ = newptr;
144 return 0;
145 trunnel_alloc_failed:
146 TRUNNEL_SET_ERROR_CODE(inp);
147 return -1;
149 const char *
150 trn_extension_field_check(const trn_extension_field_t *obj)
152 if (obj == NULL)
153 return "Object was NULL";
154 if (obj->trunnel_error_code_)
155 return "A set function failed on this object";
156 if (TRUNNEL_DYNARRAY_LEN(&obj->field) != obj->field_len)
157 return "Length mismatch for field";
158 return NULL;
161 ssize_t
162 trn_extension_field_encoded_len(const trn_extension_field_t *obj)
164 ssize_t result = 0;
166 if (NULL != trn_extension_field_check(obj))
167 return -1;
170 /* Length of u8 field_type */
171 result += 1;
173 /* Length of u8 field_len */
174 result += 1;
176 /* Length of u8 field[field_len] */
177 result += TRUNNEL_DYNARRAY_LEN(&obj->field);
178 return result;
181 trn_extension_field_clear_errors(trn_extension_field_t *obj)
183 int r = obj->trunnel_error_code_;
184 obj->trunnel_error_code_ = 0;
185 return r;
187 ssize_t
188 trn_extension_field_encode(uint8_t *output, const size_t avail, const trn_extension_field_t *obj)
190 ssize_t result = 0;
191 size_t written = 0;
192 uint8_t *ptr = output;
193 const char *msg;
194 #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 const ssize_t encoded_len = trn_extension_field_encoded_len(obj);
196 #endif
198 if (NULL != (msg = trn_extension_field_check(obj)))
199 goto check_failed;
201 #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 trunnel_assert(encoded_len >= 0);
203 #endif
205 /* Encode u8 field_type */
206 trunnel_assert(written <= avail);
207 if (avail - written < 1)
208 goto truncated;
209 trunnel_set_uint8(ptr, (obj->field_type));
210 written += 1; ptr += 1;
212 /* Encode u8 field_len */
213 trunnel_assert(written <= avail);
214 if (avail - written < 1)
215 goto truncated;
216 trunnel_set_uint8(ptr, (obj->field_len));
217 written += 1; ptr += 1;
219 /* Encode u8 field[field_len] */
221 size_t elt_len = TRUNNEL_DYNARRAY_LEN(&obj->field);
222 trunnel_assert(obj->field_len == elt_len);
223 trunnel_assert(written <= avail);
224 if (avail - written < elt_len)
225 goto truncated;
226 if (elt_len)
227 memcpy(ptr, obj->field.elts_, elt_len);
228 written += elt_len; ptr += elt_len;
232 trunnel_assert(ptr == output + written);
233 #ifdef TRUNNEL_CHECK_ENCODED_LEN
235 trunnel_assert(encoded_len >= 0);
236 trunnel_assert((size_t)encoded_len == written);
239 #endif
241 return written;
243 truncated:
244 result = -2;
245 goto fail;
246 check_failed:
247 (void)msg;
248 result = -1;
249 goto fail;
250 fail:
251 trunnel_assert(result < 0);
252 return result;
255 /** As trn_extension_field_parse(), but do not allocate the output
256 * object.
258 static ssize_t
259 trn_extension_field_parse_into(trn_extension_field_t *obj, const uint8_t *input, const size_t len_in)
261 const uint8_t *ptr = input;
262 size_t remaining = len_in;
263 ssize_t result = 0;
264 (void)result;
266 /* Parse u8 field_type */
267 CHECK_REMAINING(1, truncated);
268 obj->field_type = (trunnel_get_uint8(ptr));
269 remaining -= 1; ptr += 1;
271 /* Parse u8 field_len */
272 CHECK_REMAINING(1, truncated);
273 obj->field_len = (trunnel_get_uint8(ptr));
274 remaining -= 1; ptr += 1;
276 /* Parse u8 field[field_len] */
277 CHECK_REMAINING(obj->field_len, truncated);
278 TRUNNEL_DYNARRAY_EXPAND(uint8_t, &obj->field, obj->field_len, {});
279 obj->field.n_ = obj->field_len;
280 if (obj->field_len)
281 memcpy(obj->field.elts_, ptr, obj->field_len);
282 ptr += obj->field_len; remaining -= obj->field_len;
283 trunnel_assert(ptr + remaining == input + len_in);
284 return len_in - remaining;
286 truncated:
287 return -2;
288 trunnel_alloc_failed:
289 return -1;
292 ssize_t
293 trn_extension_field_parse(trn_extension_field_t **output, const uint8_t *input, const size_t len_in)
295 ssize_t result;
296 *output = trn_extension_field_new();
297 if (NULL == *output)
298 return -1;
299 result = trn_extension_field_parse_into(*output, input, len_in);
300 if (result < 0) {
301 trn_extension_field_free(*output);
302 *output = NULL;
304 return result;
306 trn_extension_t *
307 trn_extension_new(void)
309 trn_extension_t *val = trunnel_calloc(1, sizeof(trn_extension_t));
310 if (NULL == val)
311 return NULL;
312 return val;
315 /** Release all storage held inside 'obj', but do not free 'obj'.
317 static void
318 trn_extension_clear(trn_extension_t *obj)
320 (void) obj;
323 unsigned idx;
324 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
325 trn_extension_field_free(TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
328 TRUNNEL_DYNARRAY_WIPE(&obj->fields);
329 TRUNNEL_DYNARRAY_CLEAR(&obj->fields);
332 void
333 trn_extension_free(trn_extension_t *obj)
335 if (obj == NULL)
336 return;
337 trn_extension_clear(obj);
338 trunnel_memwipe(obj, sizeof(trn_extension_t));
339 trunnel_free_(obj);
342 uint8_t
343 trn_extension_get_num(const trn_extension_t *inp)
345 return inp->num;
348 trn_extension_set_num(trn_extension_t *inp, uint8_t val)
350 inp->num = val;
351 return 0;
353 size_t
354 trn_extension_getlen_fields(const trn_extension_t *inp)
356 return TRUNNEL_DYNARRAY_LEN(&inp->fields);
359 struct trn_extension_field_st *
360 trn_extension_get_fields(trn_extension_t *inp, size_t idx)
362 return TRUNNEL_DYNARRAY_GET(&inp->fields, idx);
365 const struct trn_extension_field_st *
366 trn_extension_getconst_fields(const trn_extension_t *inp, size_t idx)
368 return trn_extension_get_fields((trn_extension_t*)inp, idx);
371 trn_extension_set_fields(trn_extension_t *inp, size_t idx, struct trn_extension_field_st * elt)
373 trn_extension_field_t *oldval = TRUNNEL_DYNARRAY_GET(&inp->fields, idx);
374 if (oldval && oldval != elt)
375 trn_extension_field_free(oldval);
376 return trn_extension_set0_fields(inp, idx, elt);
379 trn_extension_set0_fields(trn_extension_t *inp, size_t idx, struct trn_extension_field_st * elt)
381 TRUNNEL_DYNARRAY_SET(&inp->fields, idx, elt);
382 return 0;
385 trn_extension_add_fields(trn_extension_t *inp, struct trn_extension_field_st * elt)
387 #if SIZE_MAX >= UINT8_MAX
388 if (inp->fields.n_ == UINT8_MAX)
389 goto trunnel_alloc_failed;
390 #endif
391 TRUNNEL_DYNARRAY_ADD(struct trn_extension_field_st *, &inp->fields, elt, {});
392 return 0;
393 trunnel_alloc_failed:
394 TRUNNEL_SET_ERROR_CODE(inp);
395 return -1;
398 struct trn_extension_field_st * *
399 trn_extension_getarray_fields(trn_extension_t *inp)
401 return inp->fields.elts_;
403 const struct trn_extension_field_st * const *
404 trn_extension_getconstarray_fields(const trn_extension_t *inp)
406 return (const struct trn_extension_field_st * const *)trn_extension_getarray_fields((trn_extension_t*)inp);
409 trn_extension_setlen_fields(trn_extension_t *inp, size_t newlen)
411 struct trn_extension_field_st * *newptr;
412 #if UINT8_MAX < SIZE_MAX
413 if (newlen > UINT8_MAX)
414 goto trunnel_alloc_failed;
415 #endif
416 newptr = trunnel_dynarray_setlen(&inp->fields.allocated_,
417 &inp->fields.n_, inp->fields.elts_, newlen,
418 sizeof(inp->fields.elts_[0]), (trunnel_free_fn_t) trn_extension_field_free,
419 &inp->trunnel_error_code_);
420 if (newlen != 0 && newptr == NULL)
421 goto trunnel_alloc_failed;
422 inp->fields.elts_ = newptr;
423 return 0;
424 trunnel_alloc_failed:
425 TRUNNEL_SET_ERROR_CODE(inp);
426 return -1;
428 const char *
429 trn_extension_check(const trn_extension_t *obj)
431 if (obj == NULL)
432 return "Object was NULL";
433 if (obj->trunnel_error_code_)
434 return "A set function failed on this object";
436 const char *msg;
438 unsigned idx;
439 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
440 if (NULL != (msg = trn_extension_field_check(TRUNNEL_DYNARRAY_GET(&obj->fields, idx))))
441 return msg;
444 if (TRUNNEL_DYNARRAY_LEN(&obj->fields) != obj->num)
445 return "Length mismatch for fields";
446 return NULL;
449 ssize_t
450 trn_extension_encoded_len(const trn_extension_t *obj)
452 ssize_t result = 0;
454 if (NULL != trn_extension_check(obj))
455 return -1;
458 /* Length of u8 num */
459 result += 1;
461 /* Length of struct trn_extension_field fields[num] */
464 unsigned idx;
465 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
466 result += trn_extension_field_encoded_len(TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
469 return result;
472 trn_extension_clear_errors(trn_extension_t *obj)
474 int r = obj->trunnel_error_code_;
475 obj->trunnel_error_code_ = 0;
476 return r;
478 ssize_t
479 trn_extension_encode(uint8_t *output, const size_t avail, const trn_extension_t *obj)
481 ssize_t result = 0;
482 size_t written = 0;
483 uint8_t *ptr = output;
484 const char *msg;
485 #ifdef TRUNNEL_CHECK_ENCODED_LEN
486 const ssize_t encoded_len = trn_extension_encoded_len(obj);
487 #endif
489 if (NULL != (msg = trn_extension_check(obj)))
490 goto check_failed;
492 #ifdef TRUNNEL_CHECK_ENCODED_LEN
493 trunnel_assert(encoded_len >= 0);
494 #endif
496 /* Encode u8 num */
497 trunnel_assert(written <= avail);
498 if (avail - written < 1)
499 goto truncated;
500 trunnel_set_uint8(ptr, (obj->num));
501 written += 1; ptr += 1;
503 /* Encode struct trn_extension_field fields[num] */
506 unsigned idx;
507 for (idx = 0; idx < TRUNNEL_DYNARRAY_LEN(&obj->fields); ++idx) {
508 trunnel_assert(written <= avail);
509 result = trn_extension_field_encode(ptr, avail - written, TRUNNEL_DYNARRAY_GET(&obj->fields, idx));
510 if (result < 0)
511 goto fail; /* XXXXXXX !*/
512 written += result; ptr += result;
517 trunnel_assert(ptr == output + written);
518 #ifdef TRUNNEL_CHECK_ENCODED_LEN
520 trunnel_assert(encoded_len >= 0);
521 trunnel_assert((size_t)encoded_len == written);
524 #endif
526 return written;
528 truncated:
529 result = -2;
530 goto fail;
531 check_failed:
532 (void)msg;
533 result = -1;
534 goto fail;
535 fail:
536 trunnel_assert(result < 0);
537 return result;
540 /** As trn_extension_parse(), but do not allocate the output object.
542 static ssize_t
543 trn_extension_parse_into(trn_extension_t *obj, const uint8_t *input, const size_t len_in)
545 const uint8_t *ptr = input;
546 size_t remaining = len_in;
547 ssize_t result = 0;
548 (void)result;
550 /* Parse u8 num */
551 CHECK_REMAINING(1, truncated);
552 obj->num = (trunnel_get_uint8(ptr));
553 remaining -= 1; ptr += 1;
555 /* Parse struct trn_extension_field fields[num] */
556 TRUNNEL_DYNARRAY_EXPAND(trn_extension_field_t *, &obj->fields, obj->num, {});
558 trn_extension_field_t * elt;
559 unsigned idx;
560 for (idx = 0; idx < obj->num; ++idx) {
561 result = trn_extension_field_parse(&elt, ptr, remaining);
562 if (result < 0)
563 goto relay_fail;
564 trunnel_assert((size_t)result <= remaining);
565 remaining -= result; ptr += result;
566 TRUNNEL_DYNARRAY_ADD(trn_extension_field_t *, &obj->fields, elt, {trn_extension_field_free(elt);});
569 trunnel_assert(ptr + remaining == input + len_in);
570 return len_in - remaining;
572 truncated:
573 return -2;
574 relay_fail:
575 trunnel_assert(result < 0);
576 return result;
577 trunnel_alloc_failed:
578 return -1;
581 ssize_t
582 trn_extension_parse(trn_extension_t **output, const uint8_t *input, const size_t len_in)
584 ssize_t result;
585 *output = trn_extension_new();
586 if (NULL == *output)
587 return -1;
588 result = trn_extension_parse_into(*output, input, len_in);
589 if (result < 0) {
590 trn_extension_free(*output);
591 *output = NULL;
593 return result;