| 479 | } |
| 480 | |
| 481 | ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, |
| 482 | size_t *_bufsz) { |
| 483 | size_t dst = 0, src = 0, bufsz = *_bufsz; |
| 484 | ssize_t ret = -2; /* incomplete */ |
| 485 | |
| 486 | while (1) { |
| 487 | switch (decoder->_state) { |
| 488 | case CHUNKED_IN_CHUNK_SIZE: |
| 489 | for (;; ++src) { |
| 490 | int v; |
| 491 | if (src == bufsz) |
| 492 | goto Exit; |
| 493 | if ((v = decode_hex(buf[src])) == -1) { |
| 494 | if (decoder->_hex_count == 0) { |
| 495 | ret = -1; |
| 496 | goto Exit; |
| 497 | } |
| 498 | break; |
| 499 | } |
| 500 | if (decoder->_hex_count == sizeof(size_t) * 2) { |
| 501 | ret = -1; |
| 502 | goto Exit; |
| 503 | } |
| 504 | decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v; |
| 505 | ++decoder->_hex_count; |
| 506 | } |
| 507 | decoder->_hex_count = 0; |
| 508 | decoder->_state = CHUNKED_IN_CHUNK_EXT; |
| 509 | /* fallthru */ |
| 510 | case CHUNKED_IN_CHUNK_EXT: |
| 511 | /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */ |
| 512 | for (;; ++src) { |
| 513 | if (src == bufsz) |
| 514 | goto Exit; |
| 515 | if (buf[src] == '\012') |
| 516 | break; |
| 517 | } |
| 518 | ++src; |
| 519 | if (decoder->bytes_left_in_chunk == 0) { |
| 520 | if (decoder->consume_trailer) { |
| 521 | decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; |
| 522 | break; |
| 523 | } else { |
| 524 | goto Complete; |
| 525 | } |
| 526 | } |
| 527 | decoder->_state = CHUNKED_IN_CHUNK_DATA; |
| 528 | /* fallthru */ |
| 529 | case CHUNKED_IN_CHUNK_DATA: { |
| 530 | size_t avail = bufsz - src; |
| 531 | if (avail < decoder->bytes_left_in_chunk) { |
| 532 | if (dst != src) |
| 533 | memmove(buf + dst, buf + src, avail); |
| 534 | src += avail; |
| 535 | dst += avail; |
| 536 | decoder->bytes_left_in_chunk -= avail; |
| 537 | goto Exit; |
| 538 | } |
nothing calls this directly
no test coverage detected