| Author | Andy Green <andy@warmcat.com> 2026-09-21 06:19 UTC | | Committer | Andy Green <andy@warmcat.com> 2026-09-21 07:08 UTC | | Tree | d616be5b759e8f4403803ca7151bbd4a76420f40 Raw Patch | | | server: don't touch ws close payload at CLOSED unless the conn established | server: don't touch ws close payload at CLOSED unless the conn established
LWS_CALLBACK_CLOSED can arrive at the comms protocol for a wsi that was
never established as a builder or power conn, eg on a vhost where the
protocol init failed, or a conn dropped at the ESTABLISHED URL checks,
or one caught by a context destroy in a non-ws condition. Asking about
the peer's close payload dereferences wsi->ws, which only exists on a
conn that completed a ws upgrade, crashing the server at shutdown with
lws_get_close_length (ops-ws.c:1017)
s_callback_ws
__lws_close_free_wsi (close.c:1030)
lws_context_destroy (context.c:2467)
Bail out of the CLOSED handling unless the pss is on a vhd conn list,
ie, it actually established on /builder or /power and so has teardown
state and a ws condition. This also subsumes the !vhd check that
followed it: a pss on a vhd conn list necessarily has a vhd.
|
diff --git a/src/server/s-comms.c b/src/server/s-comms.c
index 29198ba..2b1fc36 100644
--- a/src/server/s-comms.c
+++ b/src/server/s-comms.c
@@ -655,6 +655,18 @@ s_callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user,
return -1;
case LWS_CALLBACK_CLOSED:
+ /*
+ * This can also arrive for wsis that were never established
+ * as a builder or power conn, eg on a vhost where protocol
+ * init failed, or one dropped at the ESTABLISHED URL checks.
+ * Those were never added to a vhd conn list and have no
+ * teardown state, and may not even be in a ws condition:
+ * asking about the peer's close payload dereferences wsi->ws,
+ * which only exists on a conn that got that far.
+ */
+ if (!pss || lws_dll2_is_detached(&pss->same))
+ break;
+
lwsac_free(&pss->query_ac);
/* a conn closed mid-message must not leak its reassembly */
@@ -672,14 +684,6 @@ s_callback_ws(struct lws *wsi, enum lws_callback_reasons reason, void *user,
/* remove pss from vhd->builders (active connection list) */
lws_dll2_remove(&pss->same);
- /*
- * On a vhost where protocol init failed there is no vhd and
- * the conn was never established as a builder: there is
- * nothing vhd-relative to tear down.
- */
- if (!vhd)
- break;
-
sais_builder_disconnected(vhd, wsi);
sais_resource_wellknown_remove_pss(&pss->vhd->server, pss);
|