diff options
author | Carlos Garcia Campos <cgarcia@igalia.com> | 2023-02-08 11:53:00 +0100 |
---|---|---|
committer | Carlos Garcia Campos <cgarcia@igalia.com> | 2023-02-08 11:53:00 +0100 |
commit | 1e9d2b827d97fa6b9925d697b371c0000b051c6a (patch) | |
tree | d20c0cdd77ab02a0c084b40cda714ae6b6a922a1 | |
parent | 7df98880b4273308b043d632682cc2daa55319ea (diff) | |
download | libsoup-1e9d2b827d97fa6b9925d697b371c0000b051c6a.tar.gz |
http1: fix crash when skipping respone stream with chunked enconding
When skipping the response body the given buffer is NULL, which is
not handled for chunked enconding when reading the trailers.
Fixes #323
-rw-r--r-- | libsoup/http1/soup-body-input-stream.c | 4 | ||||
-rw-r--r-- | tests/streaming-test.c | 69 |
2 files changed, 71 insertions, 2 deletions
diff --git a/libsoup/http1/soup-body-input-stream.c b/libsoup/http1/soup-body-input-stream.c index 28acae83..69a93c09 100644 --- a/libsoup/http1/soup-body-input-stream.c +++ b/libsoup/http1/soup-body-input-stream.c @@ -226,12 +226,12 @@ again: case SOUP_BODY_INPUT_STREAM_STATE_TRAILERS: nread = soup_filter_input_stream_read_line ( - fstream, buffer, count, blocking, + fstream, metabuf, sizeof (metabuf), blocking, &got_line, cancellable, error); if (nread <= 0) return nread; - if (strncmp (buffer, "\r\n", nread) || strncmp (buffer, "\n", nread)) { + if (strncmp (metabuf, "\r\n", nread) || strncmp (metabuf, "\n", nread)) { priv->chunked_state = SOUP_BODY_INPUT_STREAM_STATE_DONE; priv->eof = TRUE; } diff --git a/tests/streaming-test.c b/tests/streaming-test.c index 22153325..21e95aba 100644 --- a/tests/streaming-test.c +++ b/tests/streaming-test.c @@ -217,6 +217,74 @@ do_eof_test (gconstpointer data) soup_test_session_abort_unref (session); } +static void +do_skip (SoupSession *session, + GUri *base_uri, + const char *path) +{ + GUri *uri; + SoupMessage *msg; + GInputStream *stream; + SoupMessageMetrics *metrics; + guint64 body_size = 0; + guint64 response_body_bytes_received = 0; + GError *error = NULL; + + uri = g_uri_parse_relative (base_uri, path, SOUP_HTTP_URI_FLAGS, NULL); + msg = soup_message_new_from_uri ("GET", uri); + g_uri_unref (uri); + + soup_message_add_flags (msg, SOUP_MESSAGE_COLLECT_METRICS); + g_signal_connect (msg, "got-body-data", + G_CALLBACK (msg_got_body_data_cb), + &response_body_bytes_received); + + stream = soup_test_request_send (session, msg, NULL, 0, &error); + g_assert_no_error (error); + while (TRUE) { + gssize skipped; + + skipped = g_input_stream_skip (stream, 4096, NULL, &error); + g_assert_no_error (error); + if (skipped == 0) + break; + + body_size += skipped; + } + g_object_unref (stream); + + metrics = soup_message_get_metrics (msg); + g_assert_cmpint (body_size, ==, g_bytes_get_size (full_response)); + g_assert_cmpint (soup_message_metrics_get_response_body_size (metrics), ==, body_size); + g_assert_cmpuint (soup_message_metrics_get_response_body_bytes_received (metrics), ==, response_body_bytes_received); + if (g_str_equal (path, "chunked")) { + g_assert_cmpuint (soup_message_metrics_get_response_body_bytes_received (metrics), >, soup_message_metrics_get_response_body_size (metrics)); + } else { + g_assert_cmpuint (soup_message_metrics_get_response_body_bytes_received (metrics), ==, soup_message_metrics_get_response_body_size (metrics)); + } + if (g_str_equal (path, "content-length")) { + goffset content_length; + + content_length = soup_message_headers_get_content_length (soup_message_get_response_headers (msg)); + g_assert_cmpuint (content_length, ==, response_body_bytes_received); + } + + g_object_unref (msg); +} + +static void +do_skip_test (gconstpointer data) +{ + GUri *base_uri = (GUri *)data; + SoupSession *session; + + session = soup_test_session_new (NULL); + do_skip (session, base_uri, "chunked"); + do_skip (session, base_uri, "content-length"); + do_skip (session, base_uri, "eof"); + soup_test_session_abort_unref (session); +} + int main (int argc, char **argv) { @@ -241,6 +309,7 @@ main (int argc, char **argv) g_test_add_data_func ("/streaming/chunked", base_uri, do_chunked_test); g_test_add_data_func ("/streaming/content-length", base_uri, do_content_length_test); g_test_add_data_func ("/streaming/eof", base_uri, do_eof_test); + g_test_add_data_func ("/streaming/skip", base_uri, do_skip_test); ret = g_test_run (); |