From: Azat Khuzhin Date: Sat, 4 Nov 2017 16:13:28 +0000 (+0300) Subject: Fix crashing http server when callback do not reply in place from *gencb* X-Git-Tag: release-2.1.9-beta^2~150 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b25813800f97179b2355a7b4b3557e6a7f568df2;p=libevent Fix crashing http server when callback do not reply in place from *gencb* This is the second hunk of the first patch 5ff8eb26371c4dc56f384b2de35bea2d87814779 ("Fix crashing http server when callback do not reply in place") Fixes: #567 (cherry picked from commit 306747e51c1f0de679a3b165b9429418c89f8d6a) --- diff --git a/http.c b/http.c index db0fdc21..4a77fbb8 100644 --- a/http.c +++ b/http.c @@ -3421,6 +3421,8 @@ evhttp_handle_request(struct evhttp_request *req, void *arg) /* we have a new request on which the user needs to take action */ req->userdone = 0; + bufferevent_disable(req->evcon->bufev, EV_READ); + if (req->type == 0 || req->uri == NULL) { evhttp_send_error(req, req->response_code, NULL); return; @@ -3440,8 +3442,6 @@ evhttp_handle_request(struct evhttp_request *req, void *arg) } if ((cb = evhttp_dispatch_callback(&http->callbacks, req)) != NULL) { - bufferevent_disable(req->evcon->bufev, EV_READ); - (*cb->cb)(req, cb->cbarg); return; } diff --git a/test/regress_http.c b/test/regress_http.c index 86fdf433..b761df0d 100644 --- a/test/regress_http.c +++ b/test/regress_http.c @@ -129,7 +129,8 @@ https_bev(struct event_base *base, void *arg) } #endif static struct evhttp * -http_setup(ev_uint16_t *pport, struct event_base *base, int mask) +http_setup_gencb(ev_uint16_t *pport, struct event_base *base, int mask, + void (*cb)(struct evhttp_request *, void *), void *cbarg) { struct evhttp *myhttp; @@ -145,6 +146,8 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask) } #endif + evhttp_set_gencb(myhttp, cb, cbarg); + /* Register a callback for certain types of requests */ evhttp_set_cb(myhttp, "/test", http_basic_cb, myhttp); evhttp_set_cb(myhttp, "/timeout", http_timeout_cb, myhttp); @@ -161,6 +164,9 @@ http_setup(ev_uint16_t *pport, struct event_base *base, int mask) evhttp_set_cb(myhttp, "/", http_dispatcher_cb, base); return (myhttp); } +static struct evhttp * +http_setup(ev_uint16_t *pport, struct event_base *base, int mask) +{ return http_setup_gencb(pport, base, mask, NULL, NULL); } #ifndef NI_MAXSERV #define NI_MAXSERV 1024 @@ -4526,44 +4532,68 @@ http_request_own_test(void *arg) test_ok = 1; } +static void http_run_bev_request(struct event_base *base, int port, + const char *fmt, ...) +{ + struct bufferevent *bev = NULL; + va_list ap; + evutil_socket_t fd; + struct evbuffer *out; + + fd = http_connect("127.0.0.1", port); + + /* Stupid thing to send a request */ + bev = create_bev(base, fd, 0); + bufferevent_setcb(bev, http_readcb, http_writecb, + http_errorcb, base); + out = bufferevent_get_output(bev); + + va_start(ap, fmt); + evbuffer_add_vprintf(out, fmt, ap); + va_end(ap); + + event_base_dispatch(base); + + bufferevent_free(bev); +} static void http_request_extra_body_test(void *arg) { struct basic_test_data *data = arg; struct bufferevent *bev = NULL; - evutil_socket_t fd; ev_uint16_t port = 0; int i; - struct evhttp *http = http_setup(&port, data->base, 0); - struct evbuffer *out, *body = NULL; + struct evhttp *http = + http_setup_gencb(&port, data->base, 0, http_timeout_cb, NULL); + struct evbuffer *body = NULL; exit_base = data->base; test_ok = 0; - fd = http_connect("127.0.0.1", port); - - /* Stupid thing to send a request */ - bev = create_bev(data->base, fd, 0); - bufferevent_setcb(bev, http_readcb, http_writecb, - http_errorcb, data->base); - out = bufferevent_get_output(bev); body = evbuffer_new(); - for (i = 0; i < 10000; ++i) evbuffer_add_printf(body, "this is the body that HEAD should not have"); - evbuffer_add_printf(out, + http_run_bev_request(data->base, port, "HEAD /timeout HTTP/1.1\r\n" "Host: somehost\r\n" "Connection: close\r\n" "Content-Length: %i\r\n" - "\r\n", - (int)evbuffer_get_length(body) + "\r\n%s", + (int)evbuffer_get_length(body), + evbuffer_pullup(body, -1) ); - evbuffer_add_buffer(out, body); - - event_base_dispatch(data->base); + tt_assert(test_ok == -2); + http_run_bev_request(data->base, port, + "HEAD /__gencb__ HTTP/1.1\r\n" + "Host: somehost\r\n" + "Connection: close\r\n" + "Content-Length: %i\r\n" + "\r\n%s", + (int)evbuffer_get_length(body), + evbuffer_pullup(body, -1) + ); tt_assert(test_ok == -2); end: