diff --git a/include/proto/h1.h b/include/proto/h1.h index b6a414545..8a0e26541 100644 --- a/include/proto/h1.h +++ b/include/proto/h1.h @@ -139,22 +139,19 @@ static inline const char *h1_msg_state_str(enum h1_state msg_state) * caller must ensure that ->p points to the first byte to parse. It returns * the number of bytes parsed on success, so the caller can set msg_state to * HTTP_MSG_CHUNK_SIZE. If not enough data are available, the function does not - * change anything and returns zero. If a parse error is encountered, the - * function returns < 0. Note: this function is designed to parse wrapped CRLF - * at the end of the buffer. + * change anything and returns zero. Otherwise it returns a negative value + * indicating the error positionn relative to . Note: this function is + * designed to parse wrapped CRLF at the end of the buffer. */ -static inline int http_skip_chunk_crlf(struct http_msg *msg) +static inline int h1_skip_chunk_crlf(const struct buffer *buf, int start, int stop) { - const struct buffer *buf = msg->chn->buf; - const char *ptr; - int bytes; + const char *ptr = b_ptr(buf, start); + int bytes = 1; /* NB: we'll check data availabilty at the end. It's not a * problem because whatever we match first will be checked * against the correct length. */ - bytes = 1; - ptr = b_ptr(buf, msg->next); if (*ptr == '\r') { bytes++; ptr++; @@ -162,13 +159,12 @@ static inline int http_skip_chunk_crlf(struct http_msg *msg) ptr = buf->data; } - if (msg->next + bytes > buf->i) + if (bytes > stop - start) return 0; - if (*ptr != '\n') { - msg->err_pos = buffer_count(buf, buf->p, ptr); - return -1; - } + if (*ptr != '\n') + return -buffer_count(buf, ptr, b_ptr(buf, stop)); + return bytes; } diff --git a/src/proto_http.c b/src/proto_http.c index 3032c7faf..066204166 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -6156,11 +6156,15 @@ http_msg_forward_chunked_body(struct stream *s, struct http_msg *msg) case HTTP_MSG_CHUNK_CRLF: /* we want the CRLF after the data */ - ret = http_skip_chunk_crlf(msg); + ret = h1_skip_chunk_crlf(chn->buf, msg->next, chn->buf->i); if (ret == 0) goto missing_data_or_waiting; - if (ret < 0) + if (ret < 0) { + msg->err_pos = chn->buf->i + ret; + if (msg->err_pos < 0) + msg->err_pos += chn->buf->size; goto chunk_parsing_error; + } msg->next += ret; msg->msg_state = HTTP_MSG_CHUNK_SIZE; /* fall through for HTTP_MSG_CHUNK_SIZE */