1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 19:27:35 +00:00

LibHTTP: Fix processing terminating chunk

After encountering the terminating chunk we need to read the
trailing headers line by line, until encountering the final
empty line.

Fixes #3197
This commit is contained in:
Tom 2020-08-18 20:34:15 -06:00 committed by Andreas Kling
parent 4897eb8c3e
commit d4dae49dcd
2 changed files with 13 additions and 12 deletions

View file

@ -117,12 +117,12 @@ void Job::on_socket_connected()
m_state = State::InHeaders; m_state = State::InHeaders;
return; return;
} }
if (m_state == State::InHeaders || m_state == State::AfterChunkedEncodingTrailer) { if (m_state == State::InHeaders || m_state == State::Trailers) {
if (!can_read_line()) if (!can_read_line())
return; return;
auto line = read_line(PAGE_SIZE); auto line = read_line(PAGE_SIZE);
if (line.is_null()) { if (line.is_null()) {
if (m_state == State::AfterChunkedEncodingTrailer) { if (m_state == State::Trailers) {
// Some servers like to send two ending chunks // Some servers like to send two ending chunks
// use this fact as an excuse to ignore anything after the last chunk // use this fact as an excuse to ignore anything after the last chunk
// that is not a valid trailing header. // that is not a valid trailing header.
@ -133,7 +133,7 @@ void Job::on_socket_connected()
} }
auto chomped_line = String::copy(line, Chomp); auto chomped_line = String::copy(line, Chomp);
if (chomped_line.is_empty()) { if (chomped_line.is_empty()) {
if (m_state == State::AfterChunkedEncodingTrailer) { if (m_state == State::Trailers) {
return finish_up(); return finish_up();
} else { } else {
m_state = State::InBody; m_state = State::InBody;
@ -142,7 +142,7 @@ void Job::on_socket_connected()
} }
auto parts = chomped_line.split(':'); auto parts = chomped_line.split(':');
if (parts.is_empty()) { if (parts.is_empty()) {
if (m_state == State::AfterChunkedEncodingTrailer) { if (m_state == State::Trailers) {
// Some servers like to send two ending chunks // Some servers like to send two ending chunks
// use this fact as an excuse to ignore anything after the last chunk // use this fact as an excuse to ignore anything after the last chunk
// that is not a valid trailing header. // that is not a valid trailing header.
@ -153,7 +153,7 @@ void Job::on_socket_connected()
} }
auto name = parts[0]; auto name = parts[0];
if (chomped_line.length() < name.length() + 2) { if (chomped_line.length() < name.length() + 2) {
if (m_state == State::AfterChunkedEncodingTrailer) { if (m_state == State::Trailers) {
// Some servers like to send two ending chunks // Some servers like to send two ending chunks
// use this fact as an excuse to ignore anything after the last chunk // use this fact as an excuse to ignore anything after the last chunk
// that is not a valid trailing header. // that is not a valid trailing header.
@ -186,7 +186,7 @@ void Job::on_socket_connected()
#endif #endif
if (size_lines.size() == 0) { if (size_lines.size() == 0) {
dbg() << "Job: Reached end of stream"; dbg() << "Job: Reached end of stream";
m_state = State::AfterChunkedEncodingTrailer; finish_up();
return IterationDecision::Break; return IterationDecision::Break;
} else { } else {
auto chunk = size_lines[0].split_view(';', true); auto chunk = size_lines[0].split_view(';', true);
@ -264,6 +264,12 @@ void Job::on_socket_connected()
#ifdef JOB_DEBUG #ifdef JOB_DEBUG
dbg() << "Job: Finished a chunk of " << m_current_chunk_total_size.value() << " bytes"; dbg() << "Job: Finished a chunk of " << m_current_chunk_total_size.value() << " bytes";
#endif #endif
if (m_current_chunk_total_size.value() == 0) {
m_state = State::Trailers;
return IterationDecision::Break;
}
// we've read everything, now let's get the next chunk // we've read everything, now let's get the next chunk
size = -1; size = -1;
auto line = read_line(PAGE_SIZE); auto line = read_line(PAGE_SIZE);
@ -271,11 +277,6 @@ void Job::on_socket_connected()
dbg() << "Line following (should be empty): _" << line << "_"; dbg() << "Line following (should be empty): _" << line << "_";
#endif #endif
(void)line; (void)line;
if (m_current_chunk_total_size.value() == 0) {
m_state = State::AfterChunkedEncodingTrailer;
return IterationDecision::Break;
}
} }
m_current_chunk_remaining_size = size; m_current_chunk_remaining_size = size;
} }

View file

@ -65,8 +65,8 @@ protected:
InStatus, InStatus,
InHeaders, InHeaders,
InBody, InBody,
Trailers,
Finished, Finished,
AfterChunkedEncodingTrailer,
}; };
HttpRequest m_request; HttpRequest m_request;