1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

fix uaf in signal path

This commit is contained in:
ailin-nemui 2018-01-05 23:05:39 +01:00
parent eb18904840
commit 6e6a96d8c1

View File

@ -460,8 +460,6 @@ static int server_remove_channels(SERVER_REC *server)
void server_disconnect(SERVER_REC *server) void server_disconnect(SERVER_REC *server)
{ {
int chans;
g_return_if_fail(IS_SERVER(server)); g_return_if_fail(IS_SERVER(server));
if (server->disconnected) if (server->disconnected)
@ -480,21 +478,9 @@ void server_disconnect(SERVER_REC *server)
server->disconnected = TRUE; server->disconnected = TRUE;
signal_emit("server disconnected", 1, server); signal_emit("server disconnected", 1, server);
/* close all channels */ /* we used to destroy the handle here but it may be still in
chans = server_remove_channels(server); use during signal processing, so destroy it on unref
instead */
if (server->handle != NULL) {
if (!chans || server->connection_lost)
net_sendbuffer_destroy(server->handle, TRUE);
else {
/* we were on some channels, try to let the server
disconnect so that our quit message is guaranteed
to get displayed */
net_disconnect_later(net_sendbuffer_handle(server->handle));
net_sendbuffer_destroy(server->handle, FALSE);
}
server->handle = NULL;
}
if (server->readtag > 0) { if (server->readtag > 0) {
g_source_remove(server->readtag); g_source_remove(server->readtag);
@ -513,6 +499,8 @@ void server_ref(SERVER_REC *server)
int server_unref(SERVER_REC *server) int server_unref(SERVER_REC *server)
{ {
int chans;
g_return_val_if_fail(IS_SERVER(server), FALSE); g_return_val_if_fail(IS_SERVER(server), FALSE);
if (--server->refcount > 0) if (--server->refcount > 0)
@ -524,11 +512,28 @@ int server_unref(SERVER_REC *server)
return TRUE; return TRUE;
} }
/* close all channels */
chans = server_remove_channels(server);
/* since module initialisation uses server connected, only let /* since module initialisation uses server connected, only let
them know that the object got destroyed if the server was them know that the object got destroyed if the server was
disconnected */ disconnected */
if (server->disconnected) if (server->disconnected) {
signal_emit("server destroyed", 1, server); signal_emit("server destroyed", 1, server);
}
if (server->handle != NULL) {
if (!chans || server->connection_lost)
net_sendbuffer_destroy(server->handle, TRUE);
else {
/* we were on some channels, try to let the server
disconnect so that our quit message is guaranteed
to get displayed */
net_disconnect_later(net_sendbuffer_handle(server->handle));
net_sendbuffer_destroy(server->handle, FALSE);
}
server->handle = NULL;
}
MODULE_DATA_DEINIT(server); MODULE_DATA_DEINIT(server);
server_connect_unref(server->connrec); server_connect_unref(server->connrec);