summaryrefslogtreecommitdiffstats
path: root/plugins/picohttpparser/picohttpparser.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-15 16:16:14 +0200
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-09-15 16:16:14 +0200
commitff7305bdfe2f682857ba888c70aec2fc7cee798e (patch)
treeb5b3bdcf41d42d525906b6e8d82cdf143e74ec5d /plugins/picohttpparser/picohttpparser.c
parentf07f96c3cfaeb30f95eb1898d6cc58b200e70831 (diff)
parent601a48a63e745817cf2a4c7f3ca526e393dd3fb8 (diff)
downloadmonitoring-plugins-ff7305bdfe2f682857ba888c70aec2fc7cee798e.tar.gz
Merge branch 'master' into refactor/check_apt
Diffstat (limited to 'plugins/picohttpparser/picohttpparser.c')
-rw-r--r--plugins/picohttpparser/picohttpparser.c243
1 files changed, 137 insertions, 106 deletions
diff --git a/plugins/picohttpparser/picohttpparser.c b/plugins/picohttpparser/picohttpparser.c
index 2ae92d66..e87388b0 100644
--- a/plugins/picohttpparser/picohttpparser.c
+++ b/plugins/picohttpparser/picohttpparser.c
@@ -50,59 +50,61 @@
50# define ALIGNED(n) __attribute__((aligned(n))) 50# define ALIGNED(n) __attribute__((aligned(n)))
51#endif 51#endif
52 52
53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u) 53#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c) - 040u < 0137u)
54 54
55#define CHECK_EOF() \ 55#define CHECK_EOF() \
56 if (buf == buf_end) { \ 56 if (buf == buf_end) { \
57 *ret = -2; \ 57 *ret = -2; \
58 return NULL; \ 58 return NULL; \
59 } 59 }
60 60
61#define EXPECT_CHAR_NO_CHECK(ch) \ 61#define EXPECT_CHAR_NO_CHECK(ch) \
62 if (*buf++ != ch) { \ 62 if (*buf++ != ch) { \
63 *ret = -1; \ 63 *ret = -1; \
64 return NULL; \ 64 return NULL; \
65 } 65 }
66 66
67#define EXPECT_CHAR(ch) \ 67#define EXPECT_CHAR(ch) \
68 CHECK_EOF(); \ 68 CHECK_EOF(); \
69 EXPECT_CHAR_NO_CHECK(ch); 69 EXPECT_CHAR_NO_CHECK(ch);
70 70
71#define ADVANCE_TOKEN(tok, toklen) \ 71#define ADVANCE_TOKEN(tok, toklen) \
72 do { \ 72 do { \
73 const char *tok_start = buf; \ 73 const char *tok_start = buf; \
74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \ 74 static const char ALIGNED(16) ranges2[16] = "\000\040\177\177"; \
75 int found2; \ 75 int found2; \
76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \ 76 buf = findchar_fast(buf, buf_end, ranges2, 4, &found2); \
77 if (!found2) { \ 77 if (!found2) { \
78 CHECK_EOF(); \ 78 CHECK_EOF(); \
79 } \ 79 } \
80 while (1) { \ 80 while (1) { \
81 if (*buf == ' ') { \ 81 if (*buf == ' ') { \
82 break; \ 82 break; \
83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \ 83 } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \
84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \ 84 if ((unsigned char)*buf < '\040' || *buf == '\177') { \
85 *ret = -1; \ 85 *ret = -1; \
86 return NULL; \ 86 return NULL; \
87 } \ 87 } \
88 } \ 88 } \
89 ++buf; \ 89 ++buf; \
90 CHECK_EOF(); \ 90 CHECK_EOF(); \
91 } \ 91 } \
92 tok = tok_start; \ 92 tok = tok_start; \
93 toklen = buf - tok_start; \ 93 toklen = buf - tok_start; \
94 } while (0) 94 } while (0)
95 95
96static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 96static const char *token_char_map =
97 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0" 97 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
98 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1" 98 "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
99 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0" 99 "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
100 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 100 "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 101 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" 102 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; 103 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
104 104 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
105static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found) { 105
106static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges,
107 size_t ranges_size, int *found) {
106 *found = 0; 108 *found = 0;
107#if __SSE4_2__ 109#if __SSE4_2__
108 if (likely(buf_end - buf >= 16)) { 110 if (likely(buf_end - buf >= 16)) {
@@ -111,7 +113,8 @@ static const char *findchar_fast(const char *buf, const char *buf_end, const cha
111 size_t left = (buf_end - buf) & ~15; 113 size_t left = (buf_end - buf) & ~15;
112 do { 114 do {
113 __m128i b16 = _mm_loadu_si128((const __m128i *)buf); 115 __m128i b16 = _mm_loadu_si128((const __m128i *)buf);
114 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS); 116 int r = _mm_cmpestri(ranges16, ranges_size, b16, 16,
117 _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
115 if (unlikely(r != 16)) { 118 if (unlikely(r != 16)) {
116 buf += r; 119 buf += r;
117 *found = 1; 120 *found = 1;
@@ -130,25 +133,29 @@ static const char *findchar_fast(const char *buf, const char *buf_end, const cha
130 return buf; 133 return buf;
131} 134}
132 135
133static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret) { 136static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token,
137 size_t *token_len, int *ret) {
134 const char *token_start = buf; 138 const char *token_start = buf;
135 139
136#ifdef __SSE4_2__ 140#ifdef __SSE4_2__
137 static const char ALIGNED(16) ranges1[16] = "\0\010" /* allow HT */ 141 static const char ALIGNED(16) ranges1[16] =
138 "\012\037" /* allow SP and up to but not including DEL */ 142 "\0\010" /* allow HT */
139 "\177\177"; /* allow chars w. MSB set */ 143 "\012\037" /* allow SP and up to but not including DEL */
144 "\177\177"; /* allow chars w. MSB set */
140 int found; 145 int found;
141 buf = findchar_fast(buf, buf_end, ranges1, 6, &found); 146 buf = findchar_fast(buf, buf_end, ranges1, 6, &found);
142 if (found) 147 if (found) {
143 goto FOUND_CTL; 148 goto FOUND_CTL;
149 }
144#else 150#else
145 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */ 151 /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined
152 */
146 while (likely(buf_end - buf >= 8)) { 153 while (likely(buf_end - buf >= 8)) {
147# define DOIT() \ 154# define DOIT() \
148 do { \ 155 do { \
149 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \ 156 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \
150 goto NonPrintable; \ 157 goto NonPrintable; \
151 ++buf; \ 158 ++buf; \
152 } while (0) 159 } while (0)
153 DOIT(); 160 DOIT();
154 DOIT(); 161 DOIT();
@@ -161,7 +168,8 @@ static const char *get_token_to_eol(const char *buf, const char *buf_end, const
161# undef DOIT 168# undef DOIT
162 continue; 169 continue;
163 NonPrintable: 170 NonPrintable:
164 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 171 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) ||
172 unlikely(*buf == '\177')) {
165 goto FOUND_CTL; 173 goto FOUND_CTL;
166 } 174 }
167 ++buf; 175 ++buf;
@@ -170,7 +178,8 @@ static const char *get_token_to_eol(const char *buf, const char *buf_end, const
170 for (;; ++buf) { 178 for (;; ++buf) {
171 CHECK_EOF(); 179 CHECK_EOF();
172 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { 180 if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {
173 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) { 181 if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) ||
182 unlikely(*buf == '\177')) {
174 goto FOUND_CTL; 183 goto FOUND_CTL;
175 } 184 }
176 } 185 }
@@ -219,27 +228,28 @@ static const char *is_complete(const char *buf, const char *buf_end, size_t last
219 return NULL; 228 return NULL;
220} 229}
221 230
222#define PARSE_INT(valp_, mul_) \ 231#define PARSE_INT(valp_, mul_) \
223 if (*buf < '0' || '9' < *buf) { \ 232 if (*buf < '0' || '9' < *buf) { \
224 buf++; \ 233 buf++; \
225 *ret = -1; \ 234 *ret = -1; \
226 return NULL; \ 235 return NULL; \
227 } \ 236 } \
228 *(valp_) = (mul_) * (*buf++ - '0'); 237 *(valp_) = (mul_) * (*buf++ - '0');
229 238
230#define PARSE_INT_3(valp_) \ 239#define PARSE_INT_3(valp_) \
231 do { \ 240 do { \
232 int res_ = 0; \ 241 int res_ = 0; \
233 PARSE_INT(&res_, 100) \ 242 PARSE_INT(&res_, 100) \
234 *valp_ = res_; \ 243 *valp_ = res_; \
235 PARSE_INT(&res_, 10) \ 244 PARSE_INT(&res_, 10) \
236 *valp_ += res_; \ 245 *valp_ += res_; \
237 PARSE_INT(&res_, 1) \ 246 PARSE_INT(&res_, 1) \
238 *valp_ += res_; \ 247 *valp_ += res_; \
239 } while (0) 248 } while (0)
240 249
241/* returned pointer is always within [buf, buf_end), or null */ 250/* returned pointer is always within [buf, buf_end), or null */
242static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *ret) { 251static const char *parse_http_version(const char *buf, const char *buf_end, int *major_version,
252 int *minor_version, int *ret) {
243 /* we want at least [HTTP/1.<two chars>] to try to parse */ 253 /* we want at least [HTTP/1.<two chars>] to try to parse */
244 if (buf_end - buf < 9) { 254 if (buf_end - buf < 9) {
245 *ret = -2; 255 *ret = -2;
@@ -260,8 +270,8 @@ static const char *parse_http_version(const char *buf, const char *buf_end, int
260 return buf; 270 return buf;
261} 271}
262 272
263static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers, size_t max_headers, 273static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers,
264 int *ret) { 274 size_t *num_headers, size_t max_headers, int *ret) {
265 for (;; ++*num_headers) { 275 for (;; ++*num_headers) {
266 CHECK_EOF(); 276 CHECK_EOF();
267 if (*buf == '\015') { 277 if (*buf == '\015') {
@@ -337,9 +347,10 @@ static const char *parse_headers(const char *buf, const char *buf_end, struct ph
337 return buf; 347 return buf;
338} 348}
339 349
340static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path, 350static const char *parse_request(const char *buf, const char *buf_end, const char **method,
341 size_t *path_len, int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, 351 size_t *method_len, const char **path, size_t *path_len,
342 size_t max_headers, int *ret) { 352 int *major_version, int *minor_version, struct phr_header *headers,
353 size_t *num_headers, size_t max_headers, int *ret) {
343 /* skip first empty line (some clients add CRLF after POST content) */ 354 /* skip first empty line (some clients add CRLF after POST content) */
344 CHECK_EOF(); 355 CHECK_EOF();
345 if (*buf == '\015') { 356 if (*buf == '\015') {
@@ -378,8 +389,9 @@ static const char *parse_request(const char *buf, const char *buf_end, const cha
378 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); 389 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
379} 390}
380 391
381int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len, 392int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len,
382 int *major_version, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len) { 393 const char **path, size_t *path_len, int *major_version, int *minor_version,
394 struct phr_header *headers, size_t *num_headers, size_t last_len) {
383 const char *buf = buf_start, *buf_end = buf_start + len; 395 const char *buf = buf_start, *buf_end = buf_start + len;
384 size_t max_headers = *num_headers; 396 size_t max_headers = *num_headers;
385 int r; 397 int r;
@@ -398,17 +410,18 @@ int phr_parse_request(const char *buf_start, size_t len, const char **method, si
398 return r; 410 return r;
399 } 411 }
400 412
401 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version, minor_version, headers, num_headers, 413 if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, major_version,
402 max_headers, &r)) == NULL) { 414 minor_version, headers, num_headers, max_headers, &r)) == NULL) {
403 return r; 415 return r;
404 } 416 }
405 417
406 return (int)(buf - buf_start); 418 return (int)(buf - buf_start);
407} 419}
408 420
409static const char *parse_response(const char *buf, const char *buf_end, int *major_version, int *minor_version, int *status, 421static const char *parse_response(const char *buf, const char *buf_end, int *major_version,
410 const char **msg, size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, 422 int *minor_version, int *status, const char **msg,
411 int *ret) { 423 size_t *msg_len, struct phr_header *headers, size_t *num_headers,
424 size_t max_headers, int *ret) {
412 /* parse "HTTP/1.x" */ 425 /* parse "HTTP/1.x" */
413 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) { 426 if ((buf = parse_http_version(buf, buf_end, major_version, minor_version, ret)) == NULL) {
414 return NULL; 427 return NULL;
@@ -421,7 +434,8 @@ static const char *parse_response(const char *buf, const char *buf_end, int *maj
421 do { 434 do {
422 ++buf; 435 ++buf;
423 } while (*buf == ' '); 436 } while (*buf == ' ');
424 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */ 437 /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse
438 */
425 if (buf_end - buf < 4) { 439 if (buf_end - buf < 4) {
426 *ret = -2; 440 *ret = -2;
427 return NULL; 441 return NULL;
@@ -449,8 +463,9 @@ static const char *parse_response(const char *buf, const char *buf_end, int *maj
449 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret); 463 return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
450} 464}
451 465
452int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version, int *status, const char **msg, 466int phr_parse_response(const char *buf_start, size_t len, int *major_version, int *minor_version,
453 size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t last_len) { 467 int *status, const char **msg, size_t *msg_len, struct phr_header *headers,
468 size_t *num_headers, size_t last_len) {
454 const char *buf = buf_start, *buf_end = buf + len; 469 const char *buf = buf_start, *buf_end = buf + len;
455 size_t max_headers = *num_headers; 470 size_t max_headers = *num_headers;
456 int r; 471 int r;
@@ -468,15 +483,16 @@ int phr_parse_response(const char *buf_start, size_t len, int *major_version, in
468 return r; 483 return r;
469 } 484 }
470 485
471 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == 486 if ((buf = parse_response(buf, buf_end, major_version, minor_version, status, msg, msg_len,
472 NULL) { 487 headers, num_headers, max_headers, &r)) == NULL) {
473 return r; 488 return r;
474 } 489 }
475 490
476 return (int)(buf - buf_start); 491 return (int)(buf - buf_start);
477} 492}
478 493
479int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len) { 494int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers,
495 size_t *num_headers, size_t last_len) {
480 const char *buf = buf_start, *buf_end = buf + len; 496 const char *buf = buf_start, *buf_end = buf + len;
481 size_t max_headers = *num_headers; 497 size_t max_headers = *num_headers;
482 int r; 498 int r;
@@ -526,8 +542,9 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
526 case CHUNKED_IN_CHUNK_SIZE: 542 case CHUNKED_IN_CHUNK_SIZE:
527 for (;; ++src) { 543 for (;; ++src) {
528 int v; 544 int v;
529 if (src == bufsz) 545 if (src == bufsz) {
530 goto Exit; 546 goto Exit;
547 }
531 if ((v = decode_hex(buf[src])) == -1) { 548 if ((v = decode_hex(buf[src])) == -1) {
532 if (decoder->_hex_count == 0) { 549 if (decoder->_hex_count == 0) {
533 ret = -1; 550 ret = -1;
@@ -548,10 +565,12 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
548 case CHUNKED_IN_CHUNK_EXT: 565 case CHUNKED_IN_CHUNK_EXT:
549 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */ 566 /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */
550 for (;; ++src) { 567 for (;; ++src) {
551 if (src == bufsz) 568 if (src == bufsz) {
552 goto Exit; 569 goto Exit;
553 if (buf[src] == '\012') 570 }
571 if (buf[src] == '\012') {
554 break; 572 break;
573 }
555 } 574 }
556 ++src; 575 ++src;
557 if (decoder->bytes_left_in_chunk == 0) { 576 if (decoder->bytes_left_in_chunk == 0) {
@@ -567,15 +586,17 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
567 case CHUNKED_IN_CHUNK_DATA: { 586 case CHUNKED_IN_CHUNK_DATA: {
568 size_t avail = bufsz - src; 587 size_t avail = bufsz - src;
569 if (avail < decoder->bytes_left_in_chunk) { 588 if (avail < decoder->bytes_left_in_chunk) {
570 if (dst != src) 589 if (dst != src) {
571 memmove(buf + dst, buf + src, avail); 590 memmove(buf + dst, buf + src, avail);
591 }
572 src += avail; 592 src += avail;
573 dst += avail; 593 dst += avail;
574 decoder->bytes_left_in_chunk -= avail; 594 decoder->bytes_left_in_chunk -= avail;
575 goto Exit; 595 goto Exit;
576 } 596 }
577 if (dst != src) 597 if (dst != src) {
578 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk); 598 memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);
599 }
579 src += decoder->bytes_left_in_chunk; 600 src += decoder->bytes_left_in_chunk;
580 dst += decoder->bytes_left_in_chunk; 601 dst += decoder->bytes_left_in_chunk;
581 decoder->bytes_left_in_chunk = 0; 602 decoder->bytes_left_in_chunk = 0;
@@ -584,10 +605,12 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
584 /* fallthru */ 605 /* fallthru */
585 case CHUNKED_IN_CHUNK_CRLF: 606 case CHUNKED_IN_CHUNK_CRLF:
586 for (;; ++src) { 607 for (;; ++src) {
587 if (src == bufsz) 608 if (src == bufsz) {
588 goto Exit; 609 goto Exit;
589 if (buf[src] != '\015') 610 }
611 if (buf[src] != '\015') {
590 break; 612 break;
613 }
591 } 614 }
592 if (buf[src] != '\012') { 615 if (buf[src] != '\012') {
593 ret = -1; 616 ret = -1;
@@ -598,21 +621,26 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
598 break; 621 break;
599 case CHUNKED_IN_TRAILERS_LINE_HEAD: 622 case CHUNKED_IN_TRAILERS_LINE_HEAD:
600 for (;; ++src) { 623 for (;; ++src) {
601 if (src == bufsz) 624 if (src == bufsz) {
602 goto Exit; 625 goto Exit;
603 if (buf[src] != '\015') 626 }
627 if (buf[src] != '\015') {
604 break; 628 break;
629 }
605 } 630 }
606 if (buf[src++] == '\012') 631 if (buf[src++] == '\012') {
607 goto Complete; 632 goto Complete;
633 }
608 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE; 634 decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;
609 /* fallthru */ 635 /* fallthru */
610 case CHUNKED_IN_TRAILERS_LINE_MIDDLE: 636 case CHUNKED_IN_TRAILERS_LINE_MIDDLE:
611 for (;; ++src) { 637 for (;; ++src) {
612 if (src == bufsz) 638 if (src == bufsz) {
613 goto Exit; 639 goto Exit;
614 if (buf[src] == '\012') 640 }
641 if (buf[src] == '\012') {
615 break; 642 break;
643 }
616 } 644 }
617 ++src; 645 ++src;
618 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD; 646 decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
@@ -625,13 +653,16 @@ ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_
625Complete: 653Complete:
626 ret = bufsz - src; 654 ret = bufsz - src;
627Exit: 655Exit:
628 if (dst != src) 656 if (dst != src) {
629 memmove(buf + dst, buf + src, bufsz - src); 657 memmove(buf + dst, buf + src, bufsz - src);
658 }
630 *_bufsz = dst; 659 *_bufsz = dst;
631 return ret; 660 return ret;
632} 661}
633 662
634int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) { return decoder->_state == CHUNKED_IN_CHUNK_DATA; } 663int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder) {
664 return decoder->_state == CHUNKED_IN_CHUNK_DATA;
665}
635 666
636#undef CHECK_EOF 667#undef CHECK_EOF
637#undef EXPECT_CHAR 668#undef EXPECT_CHAR