From 0caf9c5acb00083ee21a70bd219079289c0ff02f Mon Sep 17 00:00:00 2001 From: Andy Green Date: Mon, 18 Feb 2013 09:48:31 +0800 Subject: [PATCH] handle http union transition properly There's no proper transition to http union state until now. It only becomes apparant there's a problem when you try to return -1 from the HTTP callback, during the close action it will try to close() a nonsense, nonzero fd pointer in the uninitialized u.http union member. This patch takes a copy of the allocated headers struct from the u.hdr union state, transitions to u.http clearing down u and then calls the HTTP callback with URI args pointing to the still-in-scope ah allocation. After the call, the copy ah is freed. That makes sure we are in the correct union state while still giving the HTTP callback access to the URI without having to copy it around. Reported-by: Edwin can den Oetelaar Signed-off-by: Andy Green --- lib/handshake.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/handshake.c b/lib/handshake.c index 74e67cd..b21d73d 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -58,6 +58,9 @@ libwebsocket_read(struct libwebsocket_context *context, struct libwebsocket *wsi, unsigned char *buf, size_t len) { size_t n; + struct allocated_headers *ah; + char *uri_ptr; + int uri_len; switch (wsi->state) { case WSI_STATE_HTTP_ISSUING_FILE: @@ -116,7 +119,8 @@ libwebsocket_read(struct libwebsocket_context *context, goto bail; } - lwsl_info("HTTP request for '%s'\n", lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI)); + lwsl_info("HTTP request for '%s'\n", + lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI)); if (libwebsocket_ensure_user_space(wsi) == NULL) { /* drop the header info */ @@ -125,18 +129,30 @@ libwebsocket_read(struct libwebsocket_context *context, goto bail; } + /* + * Hm we still need the headers so the + * callback can look at leaders like the URI, but we + * need to transition to http union state.... hold a + * copy of u.hdr.ah and deallocate afterwards + */ + + ah = wsi->u.hdr.ah; + uri_ptr = lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI); + uri_len = lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI); + + /* union transition */ + memset(&wsi->u, 0, sizeof(wsi->u)); + wsi->state = WSI_STATE_HTTP; n = 0; if (wsi->protocol->callback) n = wsi->protocol->callback(context, wsi, LWS_CALLBACK_HTTP, - wsi->user_space, - lws_hdr_simple_ptr(wsi, WSI_TOKEN_GET_URI), - lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)); + wsi->user_space, uri_ptr, uri_len); - /* drop the header info */ - if (wsi->u.hdr.ah) - free(wsi->u.hdr.ah); + /* now drop the header info we kept a pointer to */ + if (ah) + free(ah); if (n) { lwsl_info("LWS_CALLBACK_HTTP closing\n"); -- 2.7.4