From 4ad019fd53931ae2346e894afaa469bafdb23d15 Mon Sep 17 00:00:00 2001 From: "Evgeny Grin (Karlson2k)" Date: Sun, 17 Oct 2021 16:21:04 +0300 Subject: Fixed parsing of bare CR as end-of-line in HTTP headers --- src/microhttpd/connection.c | 74 ++++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 0143986e..53e3b9ec 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c @@ -2549,42 +2549,54 @@ get_next_header_line (struct MHD_Connection *connection, return NULL; pos = 0; rbuf = connection->read_buffer; - while ( (pos < connection->read_buffer_offset - 1) && - ('\r' != rbuf[pos]) && - ('\n' != rbuf[pos]) ) - pos++; - if ( (pos == connection->read_buffer_offset - 1) && - ('\n' != rbuf[pos]) ) + mhd_assert (NULL != rbuf); + + do { - /* not found, consider growing... */ - if ( (connection->read_buffer_offset == connection->read_buffer_size) && - (! try_grow_read_buffer (connection, true)) ) + const char c = rbuf[pos]; + bool found; + found = false; + if ( ('\r' == c) && (pos < connection->read_buffer_offset - 1) && + ('\n' == rbuf[pos + 1]) ) + { /* Found CRLF */ + found = true; + if (line_len) + *line_len = pos; + rbuf[pos++] = 0; /* Replace CR with zero */ + rbuf[pos++] = 0; /* Replace LF with zero */ + } + else if ('\n' == c) /* TODO: Add MHD option to disallow */ + { /* Found bare LF */ + found = true; + if (line_len) + *line_len = pos; + rbuf[pos++] = 0; /* Replace LF with zero */ + } + if (found) { - if (NULL != connection->url) - transmit_error_response_static (connection, - MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, - REQUEST_TOO_BIG); - else - transmit_error_response_static (connection, - MHD_HTTP_URI_TOO_LONG, - REQUEST_TOO_BIG); + connection->read_buffer += pos; + connection->read_buffer_size -= pos; + connection->read_buffer_offset -= pos; + return rbuf; } - if (line_len) - *line_len = 0; - return NULL; - } + } while (++pos < connection->read_buffer_offset); + /* not found, consider growing... */ + if ( (connection->read_buffer_offset == connection->read_buffer_size) && + (! try_grow_read_buffer (connection, true)) ) + { + if (NULL != connection->url) + transmit_error_response_static (connection, + MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, + REQUEST_TOO_BIG); + else + transmit_error_response_static (connection, + MHD_HTTP_URI_TOO_LONG, + REQUEST_TOO_BIG); + } if (line_len) - *line_len = pos; - /* found, check if we have proper CRLF */ - if ( ('\r' == rbuf[pos]) && - ('\n' == rbuf[pos + 1]) ) - rbuf[pos++] = '\0'; /* skip CR if any */ - rbuf[pos++] = '\0'; /* skip LF */ - connection->read_buffer += pos; - connection->read_buffer_size -= pos; - connection->read_buffer_offset -= pos; - return rbuf; + *line_len = 0; + return NULL; } -- cgit v1.2.3