LCOV - code coverage report
Current view: top level - trunnel - sendme_cell.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 93 138 67.4 %
Date: 2021-11-24 03:28:48 Functions: 12 18 66.7 %

          Line data    Source code
       1             : /* sendme_cell.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 "sendme_cell.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 sendmecell_deadcode_dummy__ = 0;
      19             : #define OR_DEADCODE_DUMMY || sendmecell_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             : sendme_cell_t *
      32          11 : sendme_cell_new(void)
      33             : {
      34          11 :   sendme_cell_t *val = trunnel_calloc(1, sizeof(sendme_cell_t));
      35          11 :   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             : sendme_cell_clear(sendme_cell_t *obj)
      44             : {
      45             :   (void) obj;
      46             : }
      47             : 
      48             : void
      49          15 : sendme_cell_free(sendme_cell_t *obj)
      50             : {
      51          15 :   if (obj == NULL)
      52             :     return;
      53          11 :   sendme_cell_clear(obj);
      54          11 :   trunnel_memwipe(obj, sizeof(sendme_cell_t));
      55          11 :   trunnel_free_(obj);
      56             : }
      57             : 
      58             : uint8_t
      59           3 : sendme_cell_get_version(const sendme_cell_t *inp)
      60             : {
      61           3 :   return inp->version;
      62             : }
      63             : int
      64           6 : sendme_cell_set_version(sendme_cell_t *inp, uint8_t val)
      65             : {
      66           6 :   if (! ((val == 0 || val == 1))) {
      67           0 :      TRUNNEL_SET_ERROR_CODE(inp);
      68           0 :      return -1;
      69             :   }
      70           6 :   inp->version = val;
      71           6 :   return 0;
      72             : }
      73             : uint16_t
      74           6 : sendme_cell_get_data_len(const sendme_cell_t *inp)
      75             : {
      76           6 :   return inp->data_len;
      77             : }
      78             : int
      79           6 : sendme_cell_set_data_len(sendme_cell_t *inp, uint16_t val)
      80             : {
      81           6 :   inp->data_len = val;
      82           6 :   return 0;
      83             : }
      84             : size_t
      85           0 : sendme_cell_getlen_data_v1_digest(const sendme_cell_t *inp)
      86             : {
      87           0 :   (void)inp;  return TRUNNEL_SENDME_V1_DIGEST_LEN;
      88             : }
      89             : 
      90             : uint8_t
      91           0 : sendme_cell_get_data_v1_digest(sendme_cell_t *inp, size_t idx)
      92             : {
      93           0 :   trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN);
      94           0 :   return inp->data_v1_digest[idx];
      95             : }
      96             : 
      97             : uint8_t
      98           0 : sendme_cell_getconst_data_v1_digest(const sendme_cell_t *inp, size_t idx)
      99             : {
     100           0 :   return sendme_cell_get_data_v1_digest((sendme_cell_t*)inp, idx);
     101             : }
     102             : int
     103           0 : sendme_cell_set_data_v1_digest(sendme_cell_t *inp, size_t idx, uint8_t elt)
     104             : {
     105           0 :   trunnel_assert(idx < TRUNNEL_SENDME_V1_DIGEST_LEN);
     106           0 :   inp->data_v1_digest[idx] = elt;
     107           0 :   return 0;
     108             : }
     109             : 
     110             : uint8_t *
     111           8 : sendme_cell_getarray_data_v1_digest(sendme_cell_t *inp)
     112             : {
     113           8 :   return inp->data_v1_digest;
     114             : }
     115             : const uint8_t  *
     116           2 : sendme_cell_getconstarray_data_v1_digest(const sendme_cell_t *inp)
     117             : {
     118           2 :   return (const uint8_t  *)sendme_cell_getarray_data_v1_digest((sendme_cell_t*)inp);
     119             : }
     120             : const char *
     121           6 : sendme_cell_check(const sendme_cell_t *obj)
     122             : {
     123           6 :   if (obj == NULL)
     124             :     return "Object was NULL";
     125           6 :   if (obj->trunnel_error_code_)
     126             :     return "A set function failed on this object";
     127           6 :   if (! (obj->version == 0 || obj->version == 1))
     128           0 :     return "Integer out of bounds";
     129             :   switch (obj->version) {
     130             : 
     131             :     case 0:
     132             :       break;
     133             : 
     134             :     case 1:
     135             :       break;
     136             : 
     137             :     default:
     138             :         return "Bad tag for union";
     139             :       break;
     140             :   }
     141             :   return NULL;
     142             : }
     143             : 
     144             : ssize_t
     145           0 : sendme_cell_encoded_len(const sendme_cell_t *obj)
     146             : {
     147           0 :   ssize_t result = 0;
     148             : 
     149           0 :   if (NULL != sendme_cell_check(obj))
     150             :      return -1;
     151             : 
     152             : 
     153             :   /* Length of u8 version IN [0, 1] */
     154           0 :   result += 1;
     155             : 
     156             :   /* Length of u16 data_len */
     157           0 :   result += 2;
     158           0 :   switch (obj->version) {
     159             : 
     160             :     case 0:
     161             :       break;
     162             : 
     163           0 :     case 1:
     164             : 
     165             :       /* Length of u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
     166           0 :       result += TRUNNEL_SENDME_V1_DIGEST_LEN;
     167           0 :       break;
     168             : 
     169             :     default:
     170           0 :       trunnel_assert(0);
     171             :       break;
     172             :   }
     173             :   return result;
     174             : }
     175             : int
     176           0 : sendme_cell_clear_errors(sendme_cell_t *obj)
     177             : {
     178           0 :   int r = obj->trunnel_error_code_;
     179           0 :   obj->trunnel_error_code_ = 0;
     180           0 :   return r;
     181             : }
     182             : ssize_t
     183           6 : sendme_cell_encode(uint8_t *output, const size_t avail, const sendme_cell_t *obj)
     184             : {
     185           6 :   ssize_t result = 0;
     186           6 :   size_t written = 0;
     187           6 :   uint8_t *ptr = output;
     188           6 :   const char *msg;
     189             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     190             :   const ssize_t encoded_len = sendme_cell_encoded_len(obj);
     191             : #endif
     192             : 
     193           6 :   uint8_t *backptr_data_len = NULL;
     194             : 
     195           6 :   if (NULL != (msg = sendme_cell_check(obj)))
     196           0 :     goto check_failed;
     197             : 
     198             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     199             :   trunnel_assert(encoded_len >= 0);
     200             : #endif
     201             : 
     202             :   /* Encode u8 version IN [0, 1] */
     203           6 :   trunnel_assert(written <= avail);
     204           6 :   if (avail - written < 1)
     205           0 :     goto truncated;
     206           6 :   trunnel_set_uint8(ptr, (obj->version));
     207           6 :   written += 1; ptr += 1;
     208             : 
     209             :   /* Encode u16 data_len */
     210           6 :   backptr_data_len = ptr;
     211           6 :   trunnel_assert(written <= avail);
     212           6 :   if (avail - written < 2)
     213           0 :     goto truncated;
     214           6 :   trunnel_set_uint16(ptr, trunnel_htons(obj->data_len));
     215           6 :   written += 2; ptr += 2;
     216             :   {
     217           6 :     size_t written_before_union = written;
     218             : 
     219             :     /* Encode union data[version] */
     220           6 :     trunnel_assert(written <= avail);
     221           6 :     switch (obj->version) {
     222             : 
     223             :       case 0:
     224             :         break;
     225             : 
     226             :       case 1:
     227             : 
     228             :         /* Encode u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
     229           6 :         trunnel_assert(written <= avail);
     230           6 :         if (avail - written < TRUNNEL_SENDME_V1_DIGEST_LEN)
     231           0 :           goto truncated;
     232           6 :         memcpy(ptr, obj->data_v1_digest, TRUNNEL_SENDME_V1_DIGEST_LEN);
     233           6 :         written += TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN;
     234           6 :         break;
     235             : 
     236             :       default:
     237           0 :         trunnel_assert(0);
     238             :         break;
     239             :     }
     240             :     /* Write the length field back to data_len */
     241           6 :     trunnel_assert(written >= written_before_union);
     242             : #if UINT16_MAX < SIZE_MAX
     243           6 :     if (written - written_before_union > UINT16_MAX)
     244             :       goto check_failed;
     245             : #endif
     246           6 :     trunnel_set_uint16(backptr_data_len, trunnel_htons(written - written_before_union));
     247             :   }
     248             : 
     249             : 
     250           6 :   trunnel_assert(ptr == output + written);
     251             : #ifdef TRUNNEL_CHECK_ENCODED_LEN
     252             :   {
     253             :     trunnel_assert(encoded_len >= 0);
     254             :     trunnel_assert((size_t)encoded_len == written);
     255             :   }
     256             : 
     257             : #endif
     258             : 
     259           6 :   return written;
     260             : 
     261           0 :  truncated:
     262           0 :   result = -2;
     263           0 :   goto fail;
     264           0 :  check_failed:
     265           0 :   (void)msg;
     266           0 :   result = -1;
     267           0 :   goto fail;
     268             :  fail:
     269             :   trunnel_assert(result < 0);
     270             :   return result;
     271             : }
     272             : 
     273             : /** As sendme_cell_parse(), but do not allocate the output object.
     274             :  */
     275             : static ssize_t
     276           5 : sendme_cell_parse_into(sendme_cell_t *obj, const uint8_t *input, const size_t len_in)
     277             : {
     278           5 :   const uint8_t *ptr = input;
     279           5 :   size_t remaining = len_in;
     280           5 :   ssize_t result = 0;
     281           5 :   (void)result;
     282             : 
     283             :   /* Parse u8 version IN [0, 1] */
     284           5 :   CHECK_REMAINING(1, truncated);
     285           5 :   obj->version = (trunnel_get_uint8(ptr));
     286           5 :   remaining -= 1; ptr += 1;
     287           5 :   if (! (obj->version == 0 || obj->version == 1))
     288           2 :     goto fail;
     289             : 
     290             :   /* Parse u16 data_len */
     291           3 :   CHECK_REMAINING(2, truncated);
     292           3 :   obj->data_len = trunnel_ntohs(trunnel_get_uint16(ptr));
     293           3 :   remaining -= 2; ptr += 2;
     294             :   {
     295           3 :     size_t remaining_after;
     296           3 :     CHECK_REMAINING(obj->data_len, truncated);
     297           3 :     remaining_after = remaining - obj->data_len;
     298           3 :     remaining = obj->data_len;
     299             : 
     300             :     /* Parse union data[version] */
     301           3 :     switch (obj->version) {
     302             : 
     303           0 :       case 0:
     304             :         /* Skip to end of union */
     305           0 :         ptr += remaining; remaining = 0;
     306           0 :         break;
     307             : 
     308           3 :       case 1:
     309             : 
     310             :         /* Parse u8 data_v1_digest[TRUNNEL_SENDME_V1_DIGEST_LEN] */
     311           3 :         CHECK_REMAINING(TRUNNEL_SENDME_V1_DIGEST_LEN, fail);
     312           3 :         memcpy(obj->data_v1_digest, ptr, TRUNNEL_SENDME_V1_DIGEST_LEN);
     313           3 :         remaining -= TRUNNEL_SENDME_V1_DIGEST_LEN; ptr += TRUNNEL_SENDME_V1_DIGEST_LEN;
     314           3 :         break;
     315             : 
     316             :       default:
     317             :         goto fail;
     318           3 :         break;
     319             :     }
     320           3 :     if (remaining != 0)
     321           0 :       goto fail;
     322           3 :     remaining = remaining_after;
     323             :   }
     324           3 :   trunnel_assert(ptr + remaining == input + len_in);
     325           3 :   return len_in - remaining;
     326             : 
     327             :  truncated:
     328             :   return -2;
     329             :  fail:
     330           5 :   result = -1;
     331             :   return result;
     332             : }
     333             : 
     334             : ssize_t
     335           5 : sendme_cell_parse(sendme_cell_t **output, const uint8_t *input, const size_t len_in)
     336             : {
     337           5 :   ssize_t result;
     338           5 :   *output = sendme_cell_new();
     339           5 :   if (NULL == *output)
     340             :     return -1;
     341           5 :   result = sendme_cell_parse_into(*output, input, len_in);
     342           5 :   if (result < 0) {
     343           2 :     sendme_cell_free(*output);
     344           2 :     *output = NULL;
     345             :   }
     346             :   return result;
     347             : }

Generated by: LCOV version 1.14