1 /* extension.c -- generated by Trunnel v1.5.3.
2 * https://gitweb.torproject.org/trunnel.git
3 * You probably shouldn't edit this file.
6 #include "trunnel-impl.h"
10 #define TRUNNEL_SET_ERROR_CODE(obj) \
12 (obj)->trunnel_error_code_ = 1; \
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__
21 #define OR_DEADCODE_DUMMY
24 #define CHECK_REMAINING(nbytes, label) \
26 if (remaining < (nbytes) OR_DEADCODE_DUMMY) { \
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
));
40 /** Release all storage held inside 'obj', but do not free 'obj'.
43 trn_extension_field_clear(trn_extension_field_t
*obj
)
46 TRUNNEL_DYNARRAY_WIPE(&obj
->field
);
47 TRUNNEL_DYNARRAY_CLEAR(&obj
->field
);
51 trn_extension_field_free(trn_extension_field_t
*obj
)
55 trn_extension_field_clear(obj
);
56 trunnel_memwipe(obj
, sizeof(trn_extension_field_t
));
61 trn_extension_field_get_field_type(const trn_extension_field_t
*inp
)
63 return inp
->field_type
;
66 trn_extension_field_set_field_type(trn_extension_field_t
*inp
, uint8_t val
)
68 inp
->field_type
= val
;
72 trn_extension_field_get_field_len(const trn_extension_field_t
*inp
)
74 return inp
->field_len
;
77 trn_extension_field_set_field_len(trn_extension_field_t
*inp
, uint8_t val
)
83 trn_extension_field_getlen_field(const trn_extension_field_t
*inp
)
85 return TRUNNEL_DYNARRAY_LEN(&inp
->field
);
89 trn_extension_field_get_field(trn_extension_field_t
*inp
, size_t idx
)
91 return TRUNNEL_DYNARRAY_GET(&inp
->field
, idx
);
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
);
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
);
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
;
112 TRUNNEL_DYNARRAY_ADD(uint8_t, &inp
->field
, elt
, {});
114 trunnel_alloc_failed
:
115 TRUNNEL_SET_ERROR_CODE(inp
);
120 trn_extension_field_getarray_field(trn_extension_field_t
*inp
)
122 return inp
->field
.elts_
;
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
)
133 #if UINT8_MAX < SIZE_MAX
134 if (newlen
> UINT8_MAX
)
135 goto trunnel_alloc_failed
;
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
;
145 trunnel_alloc_failed
:
146 TRUNNEL_SET_ERROR_CODE(inp
);
150 trn_extension_field_check(const trn_extension_field_t
*obj
)
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";
162 trn_extension_field_encoded_len(const trn_extension_field_t
*obj
)
166 if (NULL
!= trn_extension_field_check(obj
))
170 /* Length of u8 field_type */
173 /* Length of u8 field_len */
176 /* Length of u8 field[field_len] */
177 result
+= TRUNNEL_DYNARRAY_LEN(&obj
->field
);
181 trn_extension_field_clear_errors(trn_extension_field_t
*obj
)
183 int r
= obj
->trunnel_error_code_
;
184 obj
->trunnel_error_code_
= 0;
188 trn_extension_field_encode(uint8_t *output
, const size_t avail
, const trn_extension_field_t
*obj
)
192 uint8_t *ptr
= output
;
194 #ifdef TRUNNEL_CHECK_ENCODED_LEN
195 const ssize_t encoded_len
= trn_extension_field_encoded_len(obj
);
198 if (NULL
!= (msg
= trn_extension_field_check(obj
)))
201 #ifdef TRUNNEL_CHECK_ENCODED_LEN
202 trunnel_assert(encoded_len
>= 0);
205 /* Encode u8 field_type */
206 trunnel_assert(written
<= avail
);
207 if (avail
- written
< 1)
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)
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
)
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
);
251 trunnel_assert(result
< 0);
255 /** As trn_extension_field_parse(), but do not allocate the output
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
;
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
;
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
;
288 trunnel_alloc_failed
:
293 trn_extension_field_parse(trn_extension_field_t
**output
, const uint8_t *input
, const size_t len_in
)
296 *output
= trn_extension_field_new();
299 result
= trn_extension_field_parse_into(*output
, input
, len_in
);
301 trn_extension_field_free(*output
);
307 trn_extension_new(void)
309 trn_extension_t
*val
= trunnel_calloc(1, sizeof(trn_extension_t
));
315 /** Release all storage held inside 'obj', but do not free 'obj'.
318 trn_extension_clear(trn_extension_t
*obj
)
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
);
333 trn_extension_free(trn_extension_t
*obj
)
337 trn_extension_clear(obj
);
338 trunnel_memwipe(obj
, sizeof(trn_extension_t
));
343 trn_extension_get_num(const trn_extension_t
*inp
)
348 trn_extension_set_num(trn_extension_t
*inp
, uint8_t val
)
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
);
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
;
391 TRUNNEL_DYNARRAY_ADD(struct trn_extension_field_st
*, &inp
->fields
, elt
, {});
393 trunnel_alloc_failed
:
394 TRUNNEL_SET_ERROR_CODE(inp
);
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
;
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
;
424 trunnel_alloc_failed
:
425 TRUNNEL_SET_ERROR_CODE(inp
);
429 trn_extension_check(const trn_extension_t
*obj
)
432 return "Object was NULL";
433 if (obj
->trunnel_error_code_
)
434 return "A set function failed on this object";
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
))))
444 if (TRUNNEL_DYNARRAY_LEN(&obj
->fields
) != obj
->num
)
445 return "Length mismatch for fields";
450 trn_extension_encoded_len(const trn_extension_t
*obj
)
454 if (NULL
!= trn_extension_check(obj
))
458 /* Length of u8 num */
461 /* Length of struct trn_extension_field fields[num] */
465 for (idx
= 0; idx
< TRUNNEL_DYNARRAY_LEN(&obj
->fields
); ++idx
) {
466 result
+= trn_extension_field_encoded_len(TRUNNEL_DYNARRAY_GET(&obj
->fields
, idx
));
472 trn_extension_clear_errors(trn_extension_t
*obj
)
474 int r
= obj
->trunnel_error_code_
;
475 obj
->trunnel_error_code_
= 0;
479 trn_extension_encode(uint8_t *output
, const size_t avail
, const trn_extension_t
*obj
)
483 uint8_t *ptr
= output
;
485 #ifdef TRUNNEL_CHECK_ENCODED_LEN
486 const ssize_t encoded_len
= trn_extension_encoded_len(obj
);
489 if (NULL
!= (msg
= trn_extension_check(obj
)))
492 #ifdef TRUNNEL_CHECK_ENCODED_LEN
493 trunnel_assert(encoded_len
>= 0);
497 trunnel_assert(written
<= avail
);
498 if (avail
- written
< 1)
500 trunnel_set_uint8(ptr
, (obj
->num
));
501 written
+= 1; ptr
+= 1;
503 /* Encode struct trn_extension_field fields[num] */
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
));
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
);
536 trunnel_assert(result
< 0);
540 /** As trn_extension_parse(), but do not allocate the output object.
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
;
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
;
560 for (idx
= 0; idx
< obj
->num
; ++idx
) {
561 result
= trn_extension_field_parse(&elt
, ptr
, remaining
);
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
;
575 trunnel_assert(result
< 0);
577 trunnel_alloc_failed
:
582 trn_extension_parse(trn_extension_t
**output
, const uint8_t *input
, const size_t len_in
)
585 *output
= trn_extension_new();
588 result
= trn_extension_parse_into(*output
, input
, len_in
);
590 trn_extension_free(*output
);