diff options
Diffstat (limited to 'nss/nss_files/files-hosts.c')
-rw-r--r-- | nss/nss_files/files-hosts.c | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c index e5f5b48b72..83de650756 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -1,5 +1,5 @@ /* Hosts file parser in nss_files module. - Copyright (C) 1996-2001, 2003-2008, 2009 Free Software Foundation, Inc. + Copyright (C) 1996-2001, 2003-2009, 2011 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 @@ -129,19 +129,22 @@ _nss_files_get##name##_r (proto, \ && _res_hconf.flags & HCONF_FLAG_MULTI) \ { \ /* We have to get all host entries from the file. */ \ - const size_t tmp_buflen = MIN (buflen, 4096); \ - char tmp_buffer[tmp_buflen] \ + size_t tmp_buflen = MIN (buflen, 4096); \ + char tmp_buffer_stack[tmp_buflen] \ __attribute__ ((__aligned__ (__alignof__ (struct hostent_data))));\ + char *tmp_buffer = tmp_buffer_stack; \ struct hostent tmp_result_buf; \ int naddrs = 1; \ int naliases = 0; \ char *bufferend; \ + bool tmp_buffer_malloced = false; \ \ while (result->h_aliases[naliases] != NULL) \ ++naliases; \ \ bufferend = (char *) &result->h_aliases[naliases + 1]; \ \ + again: \ while ((status = internal_getent (&tmp_result_buf, tmp_buffer, \ tmp_buflen, errnop H_ERRNO_ARG \ EXTRA_ARGS_VALUE)) \ @@ -182,7 +185,7 @@ _nss_files_get##name##_r (proto, \ } \ /* If the real name is different add it also to the \ aliases. This means that there is a duplication \ - in the alias list but this is really the users \ + in the alias list but this is really the user's \ problem. */ \ if (strcmp (old_result->h_name, \ tmp_result_buf.h_name) != 0) \ @@ -204,7 +207,7 @@ _nss_files_get##name##_r (proto, \ *errnop = ERANGE; \ *herrnop = NETDB_INTERNAL; \ status = NSS_STATUS_TRYAGAIN; \ - break; \ + goto out; \ } \ \ new_h_addr_list = \ @@ -268,8 +271,54 @@ _nss_files_get##name##_r (proto, \ } \ } \ \ - if (status != NSS_STATUS_TRYAGAIN) \ + if (status == NSS_STATUS_TRYAGAIN) \ + { \ + size_t newsize = 2 * tmp_buflen; \ + if (tmp_buffer_malloced) \ + { \ + char *newp = realloc (tmp_buffer, newsize); \ + if (newp != NULL) \ + { \ + assert ((((uintptr_t) newp) \ + & (__alignof__ (struct hostent_data) - 1)) \ + == 0); \ + tmp_buffer = newp; \ + tmp_buflen = newsize; \ + goto again; \ + } \ + } \ + else if (!__libc_use_alloca (buflen + newsize)) \ + { \ + tmp_buffer = malloc (newsize); \ + if (tmp_buffer != NULL) \ + { \ + assert ((((uintptr_t) tmp_buffer) \ + & (__alignof__ (struct hostent_data) - 1)) \ + == 0); \ + tmp_buffer_malloced = true; \ + tmp_buflen = newsize; \ + goto again; \ + } \ + } \ + else \ + { \ + tmp_buffer \ + = extend_alloca (tmp_buffer, tmp_buflen, \ + newsize \ + + __alignof__ (struct hostent_data)); \ + tmp_buffer = (char *) (((uintptr_t) tmp_buffer \ + + __alignof__ (struct hostent_data) \ + - 1) \ + & ~(__alignof__ (struct hostent_data)\ + - 1)); \ + goto again; \ + } \ + } \ + else \ status = NSS_STATUS_SUCCESS; \ + out: \ + if (tmp_buffer_malloced) \ + free (tmp_buffer); \ } \ \ \ |