From 887e0ec73fcea5c68aee2adb32db92f80519cad9 Mon Sep 17 00:00:00 2001 From: Jessie Murray Date: Sat, 4 Dec 2021 19:59:04 -0800 Subject: [PATCH] Only call ws_client_free once all scheduled events have triggered Fixes #209. A WS client socket closure could cause Webdis to schedule the send of a closing frame, leading to both EV_READ and EV_WRITE scheduled events. They would both fail and each lead to a call to ws_client_free, causing a double free that ends in a crash. --- src/websocket.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/websocket.c b/src/websocket.c index e307de2..fcc6b1d 100644 --- a/src/websocket.c +++ b/src/websocket.c @@ -579,10 +579,8 @@ ws_can_read(int fd, short event, void *p) { ws->scheduled_read = 0; ret = evbuffer_read(ws->rbuf, fd, 4096); - if(ret <= 0) { - ws_client_free(ws); /* will close the socket */ - } else if(ws->close_after_events) { - ws_close_if_able(ws); + if(ret <= 0 || ws->close_after_events) { + ws_close_if_able(ws); /* will close the socket once all events have triggered */ } else { enum ws_state state = ws_process_read_data(ws, NULL); if(state == WS_READING) { /* need more data, schedule new read */ @@ -607,7 +605,7 @@ ws_can_write(int fd, short event, void *p) { ret = evbuffer_write_atmost(ws->wbuf, fd, 4096); if(ret <= 0) { - ws_client_free(ws); /* will close the socket */ + ws_close_if_able(ws); /* will close the socket once all events have triggered */ } else { if(evbuffer_get_length(ws->wbuf) > 0) { /* more data to send */ ws_schedule_write(ws);