[libsoup/carlosgc/http2-io-error-uaf, : 2/2] http2: ensure connection is alive on IO finished




commit 49e1fe344f74dfcd077afdb22245ceea446414f4
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Thu Oct 13 11:32:38 2022 +0200

    http2: ensure connection is alive on IO finished

 libsoup/http2/soup-client-message-io-http2.c | 12 ++++-----
 tests/http2-test.c                           | 38 ++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+), 6 deletions(-)
---
diff --git a/libsoup/http2/soup-client-message-io-http2.c b/libsoup/http2/soup-client-message-io-http2.c
index ca8eec5a..9ca2edb6 100644
--- a/libsoup/http2/soup-client-message-io-http2.c
+++ b/libsoup/http2/soup-client-message-io-http2.c
@@ -1416,6 +1416,7 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
        gpointer completion_data;
         SoupMessageIOCompletion completion;
         gboolean is_closed;
+        SoupConnection *conn;
 
         data = get_data_for_message (io, msg);
 
@@ -1431,9 +1432,9 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
         is_closed = nghttp2_session_get_stream_user_data (io->session, data->stream_id) == NULL;
         nghttp2_session_set_stream_user_data (io->session, data->stream_id, NULL);
 
-        if (!io->is_shutdown && !is_closed) {
-                SoupConnection *conn;
+        conn = g_weak_ref_get (&io->conn);
 
+        if (!io->is_shutdown && !is_closed) {
                 NGCHECK (nghttp2_submit_rst_stream (io->session, NGHTTP2_FLAG_NONE, data->stream_id,
                                                     completion == SOUP_MESSAGE_IO_COMPLETE ? 
NGHTTP2_NO_ERROR : NGHTTP2_CANCEL));
                 soup_http2_message_data_close (data);
@@ -1443,11 +1444,8 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
                 if (!g_hash_table_add (io->closed_messages, data))
                         g_warn_if_reached ();
 
-                conn = g_weak_ref_get (&io->conn);
-                if (conn) {
+                if (conn)
                         soup_connection_set_in_use (conn, TRUE);
-                        g_object_unref (conn);
-                }
 
                 io_try_write (io, !io->async);
         } else {
@@ -1462,6 +1460,8 @@ soup_client_message_io_http2_finished (SoupClientMessageIO *iface,
 
         if (io->is_shutdown)
                 soup_client_message_io_http2_terminate_session (io);
+
+        g_clear_object (&conn);
 }
 
 static void
diff --git a/tests/http2-test.c b/tests/http2-test.c
index 5fd7ff01..0ec0ad54 100644
--- a/tests/http2-test.c
+++ b/tests/http2-test.c
@@ -23,6 +23,7 @@
 #include "soup-message-headers-private.h"
 #include "soup-server-message-private.h"
 #include "soup-body-input-stream-http2.h"
+#include <gio/gnetworking.h>
 
 static GUri *base_uri;
 
@@ -1143,6 +1144,24 @@ do_timeout_test (Test *test, gconstpointer data)
                 g_main_context_iteration (NULL, FALSE);
 }
 
+static void
+do_connection_closed_test (Test *test, gconstpointer data)
+{
+        GUri *uri;
+        SoupMessage *msg;
+        GInputStream *stream;
+        GError *error = NULL;
+
+        uri = g_uri_parse_relative (base_uri, "/close", SOUP_HTTP_URI_FLAGS, NULL);
+        msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
+        stream = soup_session_send (test->session, msg, NULL, &error);
+        g_assert_error (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT);
+        g_clear_error (&error);
+        g_clear_object (&stream);
+        g_object_unref (msg);
+        g_uri_unref (uri);
+}
+
 static gboolean
 unpause_message (SoupServerMessage *msg)
 {
@@ -1246,6 +1265,21 @@ server_handler (SoupServer        *server,
                                                   SOUP_MEMORY_STATIC,
                                                   "Success!", 8);
                 soup_server_message_set_status (msg, SOUP_STATUS_OK, NULL);
+        } else if (strcmp (path, "/close") == 0) {
+                SoupServerConnection *conn;
+                int fd;
+
+                conn = soup_server_message_get_connection (msg);
+                fd = g_socket_get_fd (soup_server_connection_get_socket (conn));
+#ifdef G_OS_WIN32
+                shutdown (fd, SD_SEND);
+#else
+                shutdown (fd, SHUT_WR);
+#endif
+
+                soup_server_message_set_response (msg, "text/plain",
+                                                  SOUP_MEMORY_STATIC,
+                                                  "Success!", 8);
         }
 }
 
@@ -1403,6 +1437,10 @@ main (int argc, char **argv)
                     setup_session,
                     do_timeout_test,
                     teardown_session);
+        g_test_add ("/http2/connection-closed", Test, NULL,
+                    setup_session,
+                    do_connection_closed_test,
+                    teardown_session);
 
        ret = g_test_run ();
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]