From e21cdf1e0d373ccaf01e0103e76882dcb1623fab Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 23 Jun 2012 04:08:05 +0200 Subject: [PATCH] unix: malloc only once in uv_getaddrinfo() --- src/unix/core.c | 77 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 27 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index acf35a7cc..b440506a4 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -298,9 +298,15 @@ static int uv_getaddrinfo_done(eio_req* req_) { uv__req_unregister(req->loop, req); - free(req->hints); - free(req->service); - free(req->hostname); + /* see initialization in uv_getaddrinfo() */ + if (req->hints) + free(req->hints); + else if (req->service) + free(req->service); + else if (req->hostname) + free(req->hostname); + else + assert(0); if (req->retcode == 0) { /* OK */ @@ -335,54 +341,71 @@ static void getaddrinfo_thread_proc(eio_req *req_) { } -/* stub implementation of uv_getaddrinfo */ int uv_getaddrinfo(uv_loop_t* loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb cb, const char* hostname, const char* service, const struct addrinfo* hints) { + size_t hostname_len; + size_t service_len; + size_t hints_len; eio_req* req_; + size_t len; + char* buf; + + if (req == NULL || cb == NULL || (hostname == NULL && service == NULL)) + return uv__set_artificial_error(loop, UV_EINVAL); uv_eio_init(loop); - if (req == NULL || cb == NULL || (hostname == NULL && service == NULL)) { - uv__set_artificial_error(loop, UV_EINVAL); - return -1; - } + hostname_len = hostname ? strlen(hostname) + 1 : 0; + service_len = service ? strlen(service) + 1 : 0; + hints_len = hints ? sizeof(*hints) : 0; + buf = malloc(hostname_len + service_len + hints_len); + + if (buf == NULL) + return uv__set_artificial_error(loop, UV_ENOMEM); uv__req_init(loop, req, UV_GETADDRINFO); req->loop = loop; req->cb = cb; - - /* TODO don't alloc so much. */ - - if (hints) { - req->hints = malloc(sizeof(struct addrinfo)); - memcpy(req->hints, hints, sizeof(struct addrinfo)); - } - else { - req->hints = NULL; - } - - /* TODO security! check lengths, check return values. */ - - req->hostname = hostname ? strdup(hostname) : NULL; - req->service = service ? strdup(service) : NULL; req->res = NULL; + req->hints = NULL; + req->service = NULL; + req->hostname = NULL; req->retcode = 0; - /* TODO check handle->hostname == NULL */ - /* TODO check handle->service == NULL */ + /* order matters, see uv_getaddrinfo_done() */ + len = 0; + + if (hints) { + req->hints = memcpy(buf + len, hints, sizeof(*hints)); + len += sizeof(*hints); + } + + if (service) { + req->service = memcpy(buf + len, service, service_len); + len += service_len; + } + + if (hostname) { + req->hostname = memcpy(buf + len, hostname, hostname_len); + len += hostname_len; + } req_ = eio_custom(getaddrinfo_thread_proc, EIO_PRI_DEFAULT, uv_getaddrinfo_done, req, &loop->uv_eio_channel); - assert(req_); - return 0; + if (req_) + return 0; + + free(buf); + + return uv__set_artificial_error(loop, UV_ENOMEM); }