summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garcia Campos <cgarcia@igalia.com>2023-02-08 11:53:00 +0100
committerCarlos Garcia Campos <cgarcia@igalia.com>2023-02-08 11:53:00 +0100
commit1e9d2b827d97fa6b9925d697b371c0000b051c6a (patch)
treed20c0cdd77ab02a0c084b40cda714ae6b6a922a1
parent7df98880b4273308b043d632682cc2daa55319ea (diff)
downloadlibsoup-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.c4
-rw-r--r--tests/streaming-test.c69
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 ();