LCOV - code coverage report
Current view: top level - trunnel/hs - cell_common.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 169 277 61.0 %
Date: 2021-11-24 03:28:48 Functions: 27 41 65.9 %

          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             : }

Generated by: LCOV version 1.14