]> granicus.if.org Git - libevent/commitdiff
Fix crashing http server when callback do not reply in place from *gencb*
authorAzat Khuzhin <a3at.mail@gmail.com>
Sat, 4 Nov 2017 16:13:28 +0000 (19:13 +0300)
committerAzat Khuzhin <a3at.mail@gmail.com>
Sat, 4 Nov 2017 16:15:32 +0000 (19:15 +0300)
This is the second hunk of the first patch
5ff8eb26371c4dc56f384b2de35bea2d87814779 ("Fix crashing http server when
callback do not reply in place")

Fixes: #567
http.c
test/regress_http.c

diff --git a/http.c b/http.c
index db0fdc212ed20fcd71d4d3319cccb388c5e2fc84..4a77fbb864ad610084f0a67fe73b9eedc3bbfb03 100644 (file)
--- 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;
        }
index 86fdf433ffa67868cca607681632ad5670269e5a..b761df0da16f4d3fead0c0d99d8b5584e1d017d5 100644 (file)
@@ -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: