diff --git a/lib/secure-streams/private-lib-secure-streams.h b/lib/secure-streams/private-lib-secure-streams.h index 3ae5b52a1..12d5c6081 100644 --- a/lib/secure-streams/private-lib-secure-streams.h +++ b/lib/secure-streams/private-lib-secure-streams.h @@ -84,6 +84,7 @@ typedef struct lws_ss_handle { struct lwsac *imd_ac; /**< for get custom header */ #endif const lws_ss_policy_t *rideshare; + struct lws_ss_handle *h_in_svc; #if defined(LWS_WITH_CONMON) char *conmon_json; @@ -317,6 +318,12 @@ typedef struct lws_sspc_handle { struct lws_dsh *dsh; struct lws_context *context; + struct lws_sspc_handle *h_in_svc; + /* + * Used to detect illegal lws_sspc_destroy() calls while still + * being serviced + */ + lws_usec_t us_earliest_write_req; unsigned long writeable_len; diff --git a/lib/secure-streams/secure-streams-client.c b/lib/secure-streams/secure-streams-client.c index f12db0129..602813bb9 100644 --- a/lib/secure-streams/secure-streams-client.c +++ b/lib/secure-streams/secure-streams-client.c @@ -23,6 +23,8 @@ lws_ss_state_return_t lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, lws_ss_tx_ordinal_t flags) { + lws_ss_state_return_t ret; + if (!h) return LWSSSSRET_OK; @@ -32,7 +34,11 @@ lws_sspc_event_helper(lws_sspc_handle_t *h, lws_ss_constate_t cs, if (!h->ssi.state) return LWSSSSRET_OK; - return h->ssi.state((void *)((uint8_t *)&h[1]), NULL, cs, flags); + h->h_in_svc = h; + ret = h->ssi.state((void *)((uint8_t *)&h[1]), NULL, cs, flags); + h->h_in_svc = NULL; + + return ret; } static void @@ -652,6 +658,13 @@ lws_sspc_destroy(lws_sspc_handle_t **ph) h = *ph; + if (h == h->h_in_svc) { + lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n", + __func__); + assert(0); + return; + } + if (h->destroying) return; diff --git a/lib/secure-streams/secure-streams.c b/lib/secure-streams/secure-streams.c index 740b51a5c..6826e45f6 100644 --- a/lib/secure-streams/secure-streams.c +++ b/lib/secure-streams/secure-streams.c @@ -357,9 +357,11 @@ lws_ss_event_helper(lws_ss_handle_t *h, lws_ss_constate_t cs) #endif if (h->info.state) { + h->h_in_svc = h; r = h->info.state(ss_to_userobj(h), NULL, cs, cs == LWSSSCS_UNREACHABLE && h->wsi && h->wsi->dns_reachability); + h->h_in_svc = NULL; #if defined(LWS_WITH_SERVER) if ((h->info.flags & LWSSSINFLAGS_ACCEPTED) && cs == LWSSSCS_DISCONNECTED) @@ -1259,6 +1261,13 @@ lws_ss_destroy(lws_ss_handle_t **ppss) if (!h) return; + if (h == h->h_in_svc) { + lwsl_err("%s: illegal destroy, return LWSSSSRET_DESTROY_ME instead\n", + __func__); + assert(0); + return; + } + if (h->destroying) { lwsl_info("%s: reentrant destroy\n", __func__); return;