extension.c (14787B)
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" 7 8 #include "extension.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 extension_deadcode_dummy__ = 0; 19 #define OR_DEADCODE_DUMMY || extension_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_extension_field_t * 32 trn_extension_field_new(void) 33 { 34 trn_extension_field_t *val = trunnel_calloc(1, sizeof(trn_extension_field_t)); 35 if (NULL == val) 36 return NULL; 37 return val; 38 } 39 40 /** Release all storage held inside 'obj', but do not free 'obj'. 41 */ 42 static void 43 trn_extension_field_clear(trn_extension_field_t *obj) 44 { 45 (void) obj; 46 TRUNNEL_DYNARRAY_WIPE(&obj->field); 47 TRUNNEL_DYNARRAY_CLEAR(&obj->field); 48 } 49 50 void 51 trn_extension_field_free(trn_extension_field_t *obj) 52 { 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); 58 } 59 60 uint8_t 61 trn_extension_field_get_field_type(const trn_extension_field_t *inp) 62 { 63 return inp->field_type; 64 } 65 int 66 trn_extension_field_set_field_type(trn_extension_field_t *inp, uint8_t val) 67 { 68 inp->field_type = val; 69 return 0; 70 } 71 uint8_t 72 trn_extension_field_get_field_len(const trn_extension_field_t *inp) 73 { 74 return inp->field_len; 75 } 76 int 77 trn_extension_field_set_field_len(trn_extension_field_t *inp, uint8_t val) 78 { 79 inp->field_len = val; 80 return 0; 81 } 82 size_t 83 trn_extension_field_getlen_field(const trn_extension_field_t *inp) 84 { 85 return TRUNNEL_DYNARRAY_LEN(&inp->field); 86 } 87 88 uint8_t 89 trn_extension_field_get_field(trn_extension_field_t *inp, size_t idx) 90 { 91 return TRUNNEL_DYNARRAY_GET(&inp->field, idx); 92 } 93 94 uint8_t 95 trn_extension_field_getconst_field(const trn_extension_field_t *inp, size_t idx) 96 { 97 return trn_extension_field_get_field((trn_extension_field_t*)inp, idx); 98 } 99 int 100 trn_extension_field_set_field(trn_extension_field_t *inp, size_t idx, uint8_t elt) 101 { 102 TRUNNEL_DYNARRAY_SET(&inp->field, idx, elt); 103 return 0; 104 } 105 int 106 trn_extension_field_add_field(trn_extension_field_t *inp, uint8_t elt) 107 { 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; 117 } 118 119 uint8_t * 120 trn_extension_field_getarray_field(trn_extension_field_t *inp) 121 { 122 return inp->field.elts_; 123 } 124 const uint8_t * 125 trn_extension_field_getconstarray_field(const trn_extension_field_t *inp) 126 { 127 return (const uint8_t *)trn_extension_field_getarray_field((trn_extension_field_t*)inp); 128 } 129 int 130 trn_extension_field_setlen_field(trn_extension_field_t *inp, size_t newlen) 131 { 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; 148 } 149 const char * 150 trn_extension_field_check(const trn_extension_field_t *obj) 151 { 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; 159 } 160 161 ssize_t 162 trn_extension_field_encoded_len(const trn_extension_field_t *obj) 163 { 164 ssize_t result = 0; 165 166 if (NULL != trn_extension_field_check(obj)) 167 return -1; 168 169 170 /* Length of u8 field_type */ 171 result += 1; 172 173 /* Length of u8 field_len */ 174 result += 1; 175 176 /* Length of u8 field[field_len] */ 177 result += TRUNNEL_DYNARRAY_LEN(&obj->field); 178 return result; 179 } 180 int 181 trn_extension_field_clear_errors(trn_extension_field_t *obj) 182 { 183 int r = obj->trunnel_error_code_; 184 obj->trunnel_error_code_ = 0; 185 return r; 186 } 187 ssize_t 188 trn_extension_field_encode(uint8_t *output, const size_t avail, const trn_extension_field_t *obj) 189 { 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 197 198 if (NULL != (msg = trn_extension_field_check(obj))) 199 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 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; 211 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; 218 219 /* Encode u8 field[field_len] */ 220 { 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; 229 } 230 231 232 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 return written; 242 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; 253 } 254 255 /** As trn_extension_field_parse(), but do not allocate the output 256 * object. 257 */ 258 static ssize_t 259 trn_extension_field_parse_into(trn_extension_field_t *obj, const uint8_t *input, const size_t len_in) 260 { 261 const uint8_t *ptr = input; 262 size_t remaining = len_in; 263 ssize_t result = 0; 264 (void)result; 265 266 /* Parse u8 field_type */ 267 CHECK_REMAINING(1, truncated); 268 obj->field_type = (trunnel_get_uint8(ptr)); 269 remaining -= 1; ptr += 1; 270 271 /* Parse u8 field_len */ 272 CHECK_REMAINING(1, truncated); 273 obj->field_len = (trunnel_get_uint8(ptr)); 274 remaining -= 1; ptr += 1; 275 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; 285 286 truncated: 287 return -2; 288 trunnel_alloc_failed: 289 return -1; 290 } 291 292 ssize_t 293 trn_extension_field_parse(trn_extension_field_t **output, const uint8_t *input, const size_t len_in) 294 { 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; 303 } 304 return result; 305 } 306 trn_extension_t * 307 trn_extension_new(void) 308 { 309 trn_extension_t *val = trunnel_calloc(1, sizeof(trn_extension_t)); 310 if (NULL == val) 311 return NULL; 312 return val; 313 } 314 315 /** Release all storage held inside 'obj', but do not free 'obj'. 316 */ 317 static void 318 trn_extension_clear(trn_extension_t *obj) 319 { 320 (void) obj; 321 { 322 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)); 326 } 327 } 328 TRUNNEL_DYNARRAY_WIPE(&obj->fields); 329 TRUNNEL_DYNARRAY_CLEAR(&obj->fields); 330 } 331 332 void 333 trn_extension_free(trn_extension_t *obj) 334 { 335 if (obj == NULL) 336 return; 337 trn_extension_clear(obj); 338 trunnel_memwipe(obj, sizeof(trn_extension_t)); 339 trunnel_free_(obj); 340 } 341 342 uint8_t 343 trn_extension_get_num(const trn_extension_t *inp) 344 { 345 return inp->num; 346 } 347 int 348 trn_extension_set_num(trn_extension_t *inp, uint8_t val) 349 { 350 inp->num = val; 351 return 0; 352 } 353 size_t 354 trn_extension_getlen_fields(const trn_extension_t *inp) 355 { 356 return TRUNNEL_DYNARRAY_LEN(&inp->fields); 357 } 358 359 struct trn_extension_field_st * 360 trn_extension_get_fields(trn_extension_t *inp, size_t idx) 361 { 362 return TRUNNEL_DYNARRAY_GET(&inp->fields, idx); 363 } 364 365 const struct trn_extension_field_st * 366 trn_extension_getconst_fields(const trn_extension_t *inp, size_t idx) 367 { 368 return trn_extension_get_fields((trn_extension_t*)inp, idx); 369 } 370 int 371 trn_extension_set_fields(trn_extension_t *inp, size_t idx, struct trn_extension_field_st * elt) 372 { 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); 377 } 378 int 379 trn_extension_set0_fields(trn_extension_t *inp, size_t idx, struct trn_extension_field_st * elt) 380 { 381 TRUNNEL_DYNARRAY_SET(&inp->fields, idx, elt); 382 return 0; 383 } 384 int 385 trn_extension_add_fields(trn_extension_t *inp, struct trn_extension_field_st * elt) 386 { 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; 396 } 397 398 struct trn_extension_field_st * * 399 trn_extension_getarray_fields(trn_extension_t *inp) 400 { 401 return inp->fields.elts_; 402 } 403 const struct trn_extension_field_st * const * 404 trn_extension_getconstarray_fields(const trn_extension_t *inp) 405 { 406 return (const struct trn_extension_field_st * const *)trn_extension_getarray_fields((trn_extension_t*)inp); 407 } 408 int 409 trn_extension_setlen_fields(trn_extension_t *inp, size_t newlen) 410 { 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; 427 } 428 const char * 429 trn_extension_check(const trn_extension_t *obj) 430 { 431 if (obj == NULL) 432 return "Object was NULL"; 433 if (obj->trunnel_error_code_) 434 return "A set function failed on this object"; 435 { 436 const char *msg; 437 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; 442 } 443 } 444 if (TRUNNEL_DYNARRAY_LEN(&obj->fields) != obj->num) 445 return "Length mismatch for fields"; 446 return NULL; 447 } 448 449 ssize_t 450 trn_extension_encoded_len(const trn_extension_t *obj) 451 { 452 ssize_t result = 0; 453 454 if (NULL != trn_extension_check(obj)) 455 return -1; 456 457 458 /* Length of u8 num */ 459 result += 1; 460 461 /* Length of struct trn_extension_field fields[num] */ 462 { 463 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)); 467 } 468 } 469 return result; 470 } 471 int 472 trn_extension_clear_errors(trn_extension_t *obj) 473 { 474 int r = obj->trunnel_error_code_; 475 obj->trunnel_error_code_ = 0; 476 return r; 477 } 478 ssize_t 479 trn_extension_encode(uint8_t *output, const size_t avail, const trn_extension_t *obj) 480 { 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 488 489 if (NULL != (msg = trn_extension_check(obj))) 490 goto check_failed; 491 492 #ifdef TRUNNEL_CHECK_ENCODED_LEN 493 trunnel_assert(encoded_len >= 0); 494 #endif 495 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; 502 503 /* Encode struct trn_extension_field fields[num] */ 504 { 505 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; 513 } 514 } 515 516 517 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 return written; 527 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; 538 } 539 540 /** As trn_extension_parse(), but do not allocate the output object. 541 */ 542 static ssize_t 543 trn_extension_parse_into(trn_extension_t *obj, const uint8_t *input, const size_t len_in) 544 { 545 const uint8_t *ptr = input; 546 size_t remaining = len_in; 547 ssize_t result = 0; 548 (void)result; 549 550 /* Parse u8 num */ 551 CHECK_REMAINING(1, truncated); 552 obj->num = (trunnel_get_uint8(ptr)); 553 remaining -= 1; ptr += 1; 554 555 /* Parse struct trn_extension_field fields[num] */ 556 TRUNNEL_DYNARRAY_EXPAND(trn_extension_field_t *, &obj->fields, obj->num, {}); 557 { 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);}); 567 } 568 } 569 trunnel_assert(ptr + remaining == input + len_in); 570 return len_in - remaining; 571 572 truncated: 573 return -2; 574 relay_fail: 575 trunnel_assert(result < 0); 576 return result; 577 trunnel_alloc_failed: 578 return -1; 579 } 580 581 ssize_t 582 trn_extension_parse(trn_extension_t **output, const uint8_t *input, const size_t len_in) 583 { 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; 592 } 593 return result; 594 }