From ed203a51133ed83ba407b0d6b537e0559f86ae87 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Fri, 19 Sep 2003 16:54:11 +0000 Subject: [PATCH] free the hostent. * libsoup/soup-address.c (update_address_from_entry): free the hostent. * libsoup/soup-connection-ntlm.c (ntlm_authorize_pre): Don't leak the domain * libsoup/soup-gnutls.c (soup_gnutls_get_iochannel): Add some more iochannel initialization. Not sure how this worked before... * libsoup/soup-message.c (soup_message_cleanup_response): Renamed from soup_message_prepare (and a few things removed). * libsoup/soup-message-client-io.c (soup_message_send_request): s/soup_message_prepare/soup_message_cleanup_response/ * libsoup/soup-message-io.c (io_read): Replace the final "\r\n" with "\0" on the headers before passing them to the parse function. (io_read): Call soup_message_cleanup_response after returning an informational response so the data doesn't leak. * libsoup/soup-headers.c (soup_headers_parse): Update for soup-message-io.c:io_read change * libsoup/soup-server.c (soup_server_new, soup_server_new_with_host): Don't leak the SoupAddress. * libsoup/soup-session.c (class_init): Make PROP_PROXY_URI not CONSTRUCT_ONLY. (set_property): If the proxy uri changes, call soup_session_abort() and cleanup_hosts(). (request_finished, final_finished): Fix a bug when requeuing messages. * tests/libsoup.supp: valgrind suppression file for soup tests * tests/Makefile.am (EXTRA_DIST): dist it. (noinst_PROGRAMS): move the former check_PROGRAMS to noinst_PROGRAMS instead. --- ChangeLog | 42 +++++++++++++++++++++++++ libsoup/soup-address.c | 2 ++ libsoup/soup-connection-ntlm.c | 1 + libsoup/soup-gnutls.c | 2 ++ libsoup/soup-headers.c | 8 ++--- libsoup/soup-message-client-io.c | 2 +- libsoup/soup-message-io.c | 12 +++---- libsoup/soup-message-private.h | 9 +++--- libsoup/soup-message.c | 13 +------- libsoup/soup-message.h | 2 -- libsoup/soup-server.c | 15 +++++++-- libsoup/soup-session.c | 67 +++++++++++++++++++++++++++++++++++++--- libsoup/soup-session.h | 4 +-- libsoup/soup-types.h | 2 +- tests/Makefile.am | 16 ++++++---- tests/libsoup.supp | 14 +++++++++ 16 files changed, 166 insertions(+), 45 deletions(-) create mode 100644 tests/libsoup.supp diff --git a/ChangeLog b/ChangeLog index fa19eb4..0ab1cc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,45 @@ +2003-09-19 Dan Winship + + * libsoup/soup-address.c (update_address_from_entry): free the + hostent. + + * libsoup/soup-connection-ntlm.c (ntlm_authorize_pre): Don't leak + the domain + + * libsoup/soup-gnutls.c (soup_gnutls_get_iochannel): Add some more + iochannel initialization. Not sure how this worked before... + + * libsoup/soup-message.c (soup_message_cleanup_response): Renamed + from soup_message_prepare (and a few things removed). + + * libsoup/soup-message-client-io.c (soup_message_send_request): + s/soup_message_prepare/soup_message_cleanup_response/ + + * libsoup/soup-message-io.c (io_read): Replace the final "\r\n" + with "\0" on the headers before passing them to the parse + function. + (io_read): Call soup_message_cleanup_response after returning an + informational response so the data doesn't leak. + + * libsoup/soup-headers.c (soup_headers_parse): Update for + soup-message-io.c:io_read change + + * libsoup/soup-server.c (soup_server_new, + soup_server_new_with_host): Don't leak the SoupAddress. + + * libsoup/soup-session.c (class_init): Make PROP_PROXY_URI not + CONSTRUCT_ONLY. + (set_property): If the proxy uri changes, call + soup_session_abort() and cleanup_hosts(). + (request_finished, final_finished): Fix a bug when requeuing + messages. + + * tests/libsoup.supp: valgrind suppression file for soup tests + + * tests/Makefile.am (EXTRA_DIST): dist it. + (noinst_PROGRAMS): move the former check_PROGRAMS to + noinst_PROGRAMS instead. + 2003-09-18 Dan Winship * libsoup/soup-message.c: Add wrote_informational and diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 056ad47..1570834 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -328,6 +328,8 @@ update_address_from_entry (SoupAddress *addr, SoupDNSEntry *entry) memcpy (SOUP_ADDRESS_DATA (addr), h->h_addr, h->h_length); } + soup_dns_free_hostent (h); + if (addr->priv->name && addr->priv->sockaddr) return SOUP_STATUS_OK; else diff --git a/libsoup/soup-connection-ntlm.c b/libsoup/soup-connection-ntlm.c index 609e749..e62b4e0 100644 --- a/libsoup/soup-connection-ntlm.c +++ b/libsoup/soup-connection-ntlm.c @@ -125,6 +125,7 @@ ntlm_authorize_pre (SoupMessage *msg, gpointer user_data) header = soup_ntlm_response (nonce, username, password, NULL, domain); g_free (domain_username); g_free (password); + g_free (domain); g_free (nonce); soup_message_remove_header (msg->request_headers, "Authorization"); diff --git a/libsoup/soup-gnutls.c b/libsoup/soup-gnutls.c index 442444d..c037778 100644 --- a/libsoup/soup-gnutls.c +++ b/libsoup/soup-gnutls.c @@ -511,6 +511,8 @@ soup_gnutls_get_iochannel (GIOChannel *sock, SoupSSLType type) gchan->funcs = &soup_gnutls_channel_funcs; g_io_channel_init (gchan); g_io_channel_set_close_on_unref (gchan, TRUE); + gchan->is_readable = gchan->is_writeable = TRUE; + gchan->use_buffer = FALSE; return gchan; diff --git a/libsoup/soup-headers.c b/libsoup/soup-headers.c index 9cd3892..89a71d7 100644 --- a/libsoup/soup-headers.c +++ b/libsoup/soup-headers.c @@ -38,8 +38,8 @@ soup_headers_parse (char *str, key += 2; offset = key - str; - /* pointing at another \r means end of header */ - if (*key == '\r') break; + if (!*key) + break; /* check if first character on the line is whitespace */ if (*key == ' ' || *key == '\t') { @@ -72,8 +72,8 @@ soup_headers_parse (char *str, key [0] = '\0'; key += 2; - /* pointing at another \r means end of header */ - if (*key == '\r') break; + if (!*key) + break; val = strchr (key, ':'); /* find start of val */ diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c index 1da52e2..39cc728 100644 --- a/libsoup/soup-message-client-io.c +++ b/libsoup/soup-message-client-io.c @@ -159,7 +159,7 @@ void soup_message_send_request (SoupMessage *req, SoupSocket *sock, gboolean is_via_proxy) { - soup_message_prepare (req); + soup_message_cleanup_response (req); soup_message_io_client (req, sock, get_request_headers, parse_response_headers, diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c index 6c6a7fa..95766ca 100644 --- a/libsoup/soup-message-io.c +++ b/libsoup/soup-message-io.c @@ -469,7 +469,8 @@ io_read (SoupSocket *sock, SoupMessage *msg) if (!read_metadata (msg, SOUP_MESSAGE_IO_DOUBLE_EOL)) return; - io->read_meta_buf->len -= SOUP_MESSAGE_IO_DOUBLE_EOL_LEN; + io->read_meta_buf->len -= SOUP_MESSAGE_IO_EOL_LEN; + io->read_meta_buf->data[io->read_meta_buf->len] = '\0'; status = io->parse_headers_cb (msg, io->read_meta_buf->data, io->read_meta_buf->len, &io->read_encoding, @@ -494,10 +495,6 @@ io_read (SoupSocket *sock, SoupMessage *msg) if (io->mode == SOUP_MESSAGE_IO_CLIENT && SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) { - /* FIXME: we should clear the existing - * response headers and reason_phrase. - */ - if (msg->status_code == SOUP_STATUS_CONTINUE && io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) { /* Pause the reader, unpause the writer */ @@ -518,9 +515,10 @@ io_read (SoupSocket *sock, SoupMessage *msg) io->read_state = io_body_state (io->read_encoding); SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK; - if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) + if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) { soup_message_got_informational (msg); - else + soup_message_cleanup_response (msg); + } else soup_message_got_headers (msg); SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED; break; diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h index 3da643f..9c4efb3 100644 --- a/libsoup/soup-message-private.h +++ b/libsoup/soup-message-private.h @@ -22,12 +22,13 @@ struct SoupMessagePrivate { SoupUri *uri; }; -void soup_message_run_handlers (SoupMessage *msg, - SoupHandlerPhase invoke_phase); +void soup_message_run_handlers (SoupMessage *msg, + SoupHandlerPhase phase); -void soup_message_cleanup (SoupMessage *req); +void soup_message_cleanup (SoupMessage *req); +void soup_message_cleanup_response (SoupMessage *req); -gboolean soup_message_is_keepalive (SoupMessage *msg); +gboolean soup_message_is_keepalive (SoupMessage *msg); typedef void (*SoupMessageGetHeadersFn) (SoupMessage *msg, diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c index 80fa4aa..5db903d 100644 --- a/libsoup/soup-message.c +++ b/libsoup/soup-message.c @@ -523,20 +523,9 @@ soup_message_foreach_header (GHashTable *hash, GHFunc func, gpointer user_data) g_hash_table_foreach (hash, foreach_value_in_list, &data); } -/** - * soup_message_prepare: - * @req: a message - * - * Prepares @req to be sent, by cleaning up its prior response state - **/ void -soup_message_prepare (SoupMessage *req) +soup_message_cleanup_response (SoupMessage *req) { - soup_message_io_cancel (req); - - if (req->status != SOUP_MESSAGE_STATUS_IDLE) - req->status = SOUP_MESSAGE_STATUS_IDLE; - if (req->response.owner == SOUP_BUFFER_SYSTEM_OWNED) g_free (req->response.body); diff --git a/libsoup/soup-message.h b/libsoup/soup-message.h index cd03617..b5ee802 100644 --- a/libsoup/soup-message.h +++ b/libsoup/soup-message.h @@ -103,8 +103,6 @@ void soup_message_set_response (SoupMessage *msg, void soup_message_cancel (SoupMessage *req); -void soup_message_prepare (SoupMessage *req); - void soup_message_add_header (GHashTable *hash, const char *name, const char *value); diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c index d87b838..3ce34d6 100644 --- a/libsoup/soup-server.c +++ b/libsoup/soup-server.c @@ -142,19 +142,30 @@ new_server (SoupAddress *address, SoupProtocol proto) SoupServer * soup_server_new (SoupProtocol proto, guint port) { - return new_server (soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, port), proto); + SoupAddress *address; + SoupServer *server; + + address = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, port); + server = new_server (address, proto); + g_object_unref (address); + + return server; } SoupServer * soup_server_new_with_host (const char *host, SoupProtocol proto, guint port) { SoupAddress *address; + SoupServer *server; address = soup_address_new (host, port); if (!address) return NULL; - return new_server (address, proto); + server = new_server (address, proto); + g_object_unref (address); + + return server; } guint diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 4b33643..88c9d58 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -47,6 +47,7 @@ struct SoupSessionPrivate { static guint host_uri_hash (gconstpointer key); static gboolean host_uri_equal (gconstpointer v1, gconstpointer v2); +static void free_host (SoupSessionHost *host, SoupSession *session); static gboolean run_queue (SoupSession *session, gboolean try_pruning); @@ -95,12 +96,27 @@ init (GObject *object) session->priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT; } +static gboolean +foreach_free_host (gpointer key, gpointer host, gpointer session) +{ + free_host (host, session); + return TRUE; +} + +static void +cleanup_hosts (SoupSession *session) +{ + g_hash_table_foreach_remove (session->priv->hosts, + foreach_free_host, session); +} + static void dispose (GObject *object) { SoupSession *session = SOUP_SESSION (object); soup_session_abort (session); + cleanup_hosts (session); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -111,6 +127,8 @@ finalize (GObject *object) SoupSession *session = SOUP_SESSION (object); soup_message_queue_destroy (session->priv->queue); + g_hash_table_destroy (session->priv->hosts); + g_hash_table_destroy (session->priv->conns); g_free (session->priv); G_OBJECT_CLASS (parent_class)->finalize (object); @@ -161,7 +179,7 @@ class_init (GObjectClass *object_class) g_param_spec_pointer (SOUP_SESSION_PROXY_URI, "Proxy URI", "The HTTP Proxy to use for this session", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_READWRITE)); g_object_class_install_property ( object_class, PROP_MAX_CONNS, g_param_spec_int (SOUP_SESSION_MAX_CONNS, @@ -219,8 +237,13 @@ set_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PROXY_URI: + if (session->priv->proxy_uri) + soup_uri_free (session->priv->proxy_uri); pval = g_value_get_pointer (value); session->priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL; + + soup_session_abort (session); + cleanup_hosts (session); break; case PROP_MAX_CONNS: session->priv->max_conns = g_value_get_int (value); @@ -303,6 +326,41 @@ get_host_for_message (SoupSession *session, SoupMessage *msg) return host; } +static void +free_realm (gpointer path, gpointer scheme_realm, gpointer data) +{ + g_free (path); + g_free (scheme_realm); +} + +static void +free_auth (gpointer scheme_realm, gpointer auth, gpointer data) +{ + g_free (scheme_realm); + g_object_unref (auth); +} + +static void +free_host (SoupSessionHost *host, SoupSession *session) +{ + while (host->connections) { + SoupConnection *conn = host->connections->data; + + host->connections = g_slist_remove (host->connections, conn); + soup_connection_disconnect (conn); + } + + if (host->auth_realms) { + g_hash_table_foreach (host->auth_realms, free_realm, NULL); + g_hash_table_destroy (host->auth_realms); + } + if (host->auths) { + g_hash_table_foreach (host->auths, free_auth, NULL); + g_hash_table_destroy (host->auths); + } + + soup_uri_free (host->root_uri); +} /* Authentication */ @@ -556,7 +614,8 @@ redirect_handler (SoupMessage *msg, gpointer user_data) static void request_finished (SoupMessage *req, gpointer user_data) { - req->status = SOUP_MESSAGE_STATUS_FINISHED; + if (!SOUP_MESSAGE_IS_STARTING (req)) + req->status = SOUP_MESSAGE_STATUS_FINISHED; } static void @@ -570,9 +629,9 @@ final_finished (SoupMessage *req, gpointer user_data) g_signal_handlers_disconnect_by_func (req, request_finished, session); g_signal_handlers_disconnect_by_func (req, final_finished, session); g_object_unref (req); - - run_queue (session, FALSE); } + + run_queue (session, FALSE); } static void diff --git a/libsoup/soup-session.h b/libsoup/soup-session.h index 9b2e03a..1d35cdf 100644 --- a/libsoup/soup-session.h +++ b/libsoup/soup-session.h @@ -18,11 +18,11 @@ typedef struct SoupSessionPrivate SoupSessionPrivate; -typedef struct { +struct SoupSession { GObject parent; SoupSessionPrivate *priv; -} SoupSession; +}; typedef struct { GObjectClass parent_class; diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h index 3ba0962..6ae8801 100644 --- a/libsoup/soup-types.h +++ b/libsoup/soup-types.h @@ -13,12 +13,12 @@ typedef struct SoupAddress SoupAddress; typedef struct SoupConnection SoupConnection; -typedef struct SoupContext SoupContext; typedef struct SoupMessage SoupMessage; typedef struct SoupServer SoupServer; typedef union SoupServerAuth SoupServerAuth; typedef struct SoupServerAuthContext SoupServerAuthContext; typedef struct SoupServerMessage SoupServerMessage; +typedef struct SoupSession SoupSession; typedef struct SoupSocket SoupSocket; typedef struct SoupUri SoupUri; diff --git a/tests/Makefile.am b/tests/Makefile.am index ec1d275..58fff78 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -4,16 +4,20 @@ INCLUDES = \ LIBS = $(top_builddir)/libsoup/libsoup-$(SOUP_API_VERSION).la -noinst_PROGRAMS = get revserver simple-httpd simple-proxy +noinst_PROGRAMS = \ + auth-test \ + get \ + revserver \ + simple-httpd \ + simple-proxy \ + uri-parsing +auth_test_SOURCES = auth-test.c get_SOURCES = get.c simple_httpd_SOURCES = simple-httpd.c simple_proxy_SOURCES = simple-proxy.c - revserver_SOURCES = revserver.c revserver_LDFLAGS = `pkg-config --libs gthread-2.0` - -check_PROGRAMS = auth-test uri-parsing - -auth_test_SOURCES = auth-test.c uri_parsing_SOURCES = uri-parsing.c + +EXTRA_DIST = libsoup.supp diff --git a/tests/libsoup.supp b/tests/libsoup.supp new file mode 100644 index 0000000..a659e4f --- /dev/null +++ b/tests/libsoup.supp @@ -0,0 +1,14 @@ +# valgrind suppressions file + +{ + glib/gtype + Memcheck:Leak + fun:calloc + fun:type_node_any_new_W +} +{ + gcrypt/uninit + Memcheck:Cond + fun:* + fun:gcry_cipher_encrypt +} -- 2.7.4