From cd065b68439076971640047cc6eaada27dcfd0f7 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Thu, 12 May 2016 10:39:29 +0200 Subject: getaddrinfo: Convert from extend_alloca to struct scratch_buffer --- ChangeLog | 9 +++ sysdeps/posix/getaddrinfo.c | 151 +++++++++++++++++--------------------------- 2 files changed, 68 insertions(+), 92 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5609b5cdc0..dee85ca13e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2016-05-12 Florian Weimer + + * sysdeps/posix/getaddrinfo.c (gaih_inet_serv): Add tmpbuf + argument. Use scratch buffer instead of extend_alloca. + (gethosts): Use scratch buffer instead of extend_alloca. + (gaih_inet): Add tmpbuf argument. Use scratch buffer instead of + extend_alloca. + (getaddrinfo): Allocate scratch buffer and pass it to gaih_inet. + 2016-05-11 Joseph Myers [BZ #20055] diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c index c670a984b2..574ce08aea 100644 --- a/sysdeps/posix/getaddrinfo.c +++ b/sysdeps/posix/getaddrinfo.c @@ -1,3 +1,21 @@ +/* Host and service name lookups using Name Service Switch modules. + Copyright (C) 1996-2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + /* The Inner Net License, Version 2.00 The author(s) grant permission for redistribution and use in source and @@ -63,6 +81,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef HAVE_LIBIDN extern int __idna_to_ascii_lz (const char *input, char **output, int flags); @@ -135,24 +154,24 @@ static const struct addrinfo default_hints = static int gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp, - const struct addrinfo *req, struct gaih_servtuple *st) + const struct addrinfo *req, struct gaih_servtuple *st, + struct scratch_buffer *tmpbuf) { struct servent *s; - size_t tmpbuflen = 1024; struct servent ts; - char *tmpbuf; int r; do { - tmpbuf = __alloca (tmpbuflen); - - r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen, - &s); + r = __getservbyname_r (servicename, tp->name, &ts, + tmpbuf->data, tmpbuf->length, &s); if (r != 0 || s == NULL) { if (r == ERANGE) - tmpbuflen *= 2; + { + if (!scratch_buffer_grow (tmpbuf)) + return -EAI_MEMORY; + } else return -EAI_SERVICE; } @@ -227,26 +246,15 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req, no_data = 0; \ while (1) { \ rc = 0; \ - status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \ + status = DL_CALL_FCT (fct, (name, _family, &th, \ + tmpbuf->data, tmpbuf->length, \ &rc, &herrno, NULL, &localcanon)); \ if (rc != ERANGE || herrno != NETDB_INTERNAL) \ break; \ - if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \ - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \ - alloca_used); \ - else \ + if (!scratch_buffer_grow (tmpbuf)) \ { \ - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \ - 2 * tmpbuflen); \ - if (newp == NULL) \ - { \ - _res.options |= old_res_options & RES_USE_INET6; \ - result = -EAI_MEMORY; \ - goto free_and_return; \ - } \ - tmpbuf = newp; \ - malloc_tmpbuf = true; \ - tmpbuflen = 2 * tmpbuflen; \ + result = -EAI_MEMORY; \ + goto free_and_return; \ } \ } \ if (status == NSS_STATUS_SUCCESS && rc == 0) \ @@ -308,7 +316,7 @@ extern service_user *__nss_hosts_database attribute_hidden; static int gaih_inet (const char *name, const struct gaih_service *service, const struct addrinfo *req, struct addrinfo **pai, - unsigned int *naddrs) + unsigned int *naddrs, struct scratch_buffer *tmpbuf) { const struct gaih_typeproto *tp = gaih_inet_typeproto; struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv; @@ -317,7 +325,10 @@ gaih_inet (const char *name, const struct gaih_service *service, bool got_ipv6 = false; const char *canon = NULL; const char *orig_name = name; - size_t alloca_used = 0; + + /* Reserve stack memory for the scratch buffer in the getaddrinfo + function. */ + size_t alloca_used = sizeof (struct scratch_buffer); if (req->ai_protocol || req->ai_socktype) { @@ -352,7 +363,7 @@ gaih_inet (const char *name, const struct gaih_service *service, st = (struct gaih_servtuple *) alloca_account (sizeof (struct gaih_servtuple), alloca_used); - if ((rc = gaih_inet_serv (service->name, tp, req, st))) + if ((rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf))) return rc; } else @@ -377,7 +388,8 @@ gaih_inet (const char *name, const struct gaih_service *service, alloca_account (sizeof (struct gaih_servtuple), alloca_used); - if ((rc = gaih_inet_serv (service->name, tp, req, newp))) + if ((rc = gaih_inet_serv (service->name, + tp, req, newp, tmpbuf))) { if (rc) continue; @@ -438,9 +450,8 @@ gaih_inet (const char *name, const struct gaih_service *service, struct gaih_addrtuple *addrmem = NULL; bool malloc_canonbuf = false; char *canonbuf = NULL; - bool malloc_tmpbuf = false; - char *tmpbuf = NULL; int result = 0; + if (name != NULL) { at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used); @@ -608,11 +619,6 @@ gaih_inet (const char *name, const struct gaih_service *service, if (req->ai_family == AF_INET && (req->ai_flags & AI_CANONNAME) == 0) { - /* Allocate additional room for struct host_data. */ - size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*) - + 16 * sizeof(char)); - assert (tmpbuf == NULL); - tmpbuf = alloca_account (tmpbuflen, alloca_used); int rc; struct hostent th; struct hostent *h; @@ -620,28 +626,15 @@ gaih_inet (const char *name, const struct gaih_service *service, while (1) { - rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf, - tmpbuflen, &h, &herrno); + rc = __gethostbyname2_r (name, AF_INET, &th, + tmpbuf->data, tmpbuf->length, + &h, &herrno); if (rc != ERANGE || herrno != NETDB_INTERNAL) break; - - if (!malloc_tmpbuf - && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, - 2 * tmpbuflen, - alloca_used); - else + if (!scratch_buffer_grow (tmpbuf)) { - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, - 2 * tmpbuflen); - if (newp == NULL) - { - result = -EAI_MEMORY; - goto free_and_return; - } - tmpbuf = newp; - malloc_tmpbuf = true; - tmpbuflen = 2 * tmpbuflen; + result = -EAI_MEMORY; + goto free_and_return; } } @@ -835,22 +828,6 @@ gaih_inet (const char *name, const struct gaih_service *service, old_res_options = _res.options; _res.options &= ~RES_USE_INET6; - size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple); - malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen); - assert (tmpbuf == NULL); - if (!malloc_tmpbuf) - tmpbuf = alloca_account (tmpbuflen, alloca_used); - else - { - tmpbuf = malloc (tmpbuflen); - if (tmpbuf == NULL) - { - _res.options |= old_res_options & RES_USE_INET6; - result = -EAI_MEMORY; - goto free_and_return; - } - } - while (!no_more) { no_data = 0; @@ -868,8 +845,9 @@ gaih_inet (const char *name, const struct gaih_service *service, while (1) { rc = 0; - status = DL_CALL_FCT (fct4, (name, pat, tmpbuf, - tmpbuflen, &rc, &herrno, + status = DL_CALL_FCT (fct4, (name, pat, + tmpbuf->data, tmpbuf->length, + &rc, &herrno, NULL)); if (status == NSS_STATUS_SUCCESS) break; @@ -883,24 +861,11 @@ gaih_inet (const char *name, const struct gaih_service *service, break; } - if (!malloc_tmpbuf - && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) - tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, - 2 * tmpbuflen, - alloca_used); - else + if (!scratch_buffer_grow (tmpbuf)) { - char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, - 2 * tmpbuflen); - if (newp == NULL) - { - _res.options |= old_res_options & RES_USE_INET6; - result = -EAI_MEMORY; - goto free_and_return; - } - tmpbuf = newp; - malloc_tmpbuf = true; - tmpbuflen = 2 * tmpbuflen; + _res.options |= old_res_options & RES_USE_INET6; + result = -EAI_MEMORY; + goto free_and_return; } } @@ -1287,8 +1252,6 @@ gaih_inet (const char *name, const struct gaih_service *service, free (addrmem); if (malloc_canonbuf) free (canonbuf); - if (malloc_tmpbuf) - free (tmpbuf); return result; } @@ -2423,7 +2386,11 @@ getaddrinfo (const char *name, const char *service, if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET || hints->ai_family == AF_INET6) { - last_i = gaih_inet (name, pservice, hints, end, &naddrs); + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + last_i = gaih_inet (name, pservice, hints, end, &naddrs, &tmpbuf); + scratch_buffer_free (&tmpbuf); + if (last_i != 0) { freeaddrinfo (p); -- cgit 1.4.1