diff options
author | Florian Weimer <fweimer@redhat.com> | 2015-03-01 19:09:00 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2016-04-25 06:19:30 +0200 |
commit | e970ea40df40ab5da24c984a0612f98a798221d8 (patch) | |
tree | 9875826fe8e52373f3a478ccdbbb569c6369002d | |
parent | 34ddffb50c2d2159c152cc34516f4c4088b3cc36 (diff) | |
download | glibc-e970ea40df40ab5da24c984a0612f98a798221d8.tar.gz |
nss_files: Use struct scratch_buffer instead of extend_alloca
In both _nss_files_gethostbyname3_r and _nss_files_initgroups_dyn,
__libc_use_alloca was misused because it was not taken into account
that extend_alloca can fail to merge allocations.
[BZ #18023]
* nss/nss_files/files-hosts.c (_nss_files_gethostbyname3_r):
Use struct scratch_buffer instead of extend_alloca.
* nss/nss_files/files-initgroups.c (_nss_files_initgroups_dyn):
Likewise.
-rw-r--r-- | nss/nss_files/files-hosts.c | 64 | ||||
-rw-r--r-- | nss/nss_files/files-initgroups.c | 32 |
2 files changed, 20 insertions, 76 deletions
diff --git a/nss/nss_files/files-hosts.c b/nss/nss_files/files-hosts.c index 2a4a665d7e..8eda308853 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -22,7 +22,7 @@ #include <arpa/nameser.h> #include <netdb.h> #include <resolv.h> - +#include <scratch_buffer.h> /* Get implementation for some internal functions. */ #include "../resolv/mapv4v6addr.h" @@ -145,15 +145,12 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, && _res_hconf.flags & HCONF_FLAG_MULTI) { /* We have to get all host entries from the file. */ - 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; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); while (result->h_aliases[naliases] != NULL) ++naliases; @@ -161,9 +158,9 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, bufferend = (char *) &result->h_aliases[naliases + 1]; again: - while ((status = internal_getent (stream, &tmp_result_buf, tmp_buffer, - tmp_buflen, errnop, herrnop, af, - flags)) + while ((status = internal_getent (stream, &tmp_result_buf, + tmpbuf.data, tmpbuf.length, + errnop, herrnop, af, flags)) == NSS_STATUS_SUCCESS) { int matches = 1; @@ -287,54 +284,13 @@ _nss_files_gethostbyname3_r (const char *name, int af, struct hostent *result, } } - 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; - } - } + if (status == NSS_STATUS_TRYAGAIN + && scratch_buffer_grow (&tmpbuf)) + goto again; else status = NSS_STATUS_SUCCESS; out: - if (tmp_buffer_malloced) - free (tmp_buffer); + scratch_buffer_free (&tmpbuf); } internal_endent (&stream); diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c index 6e0d8258da..13d45cc52c 100644 --- a/nss/nss_files/files-initgroups.c +++ b/nss/nss_files/files-initgroups.c @@ -16,7 +16,6 @@ License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */ -#include <alloca.h> #include <errno.h> #include <grp.h> #include <nss.h> @@ -25,6 +24,7 @@ #include <sys/param.h> #include <stdbool.h> #include <stdlib.h> +#include <scratch_buffer.h> enum nss_status _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, @@ -46,9 +46,8 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, enum nss_status status = NSS_STATUS_SUCCESS; bool any = false; - size_t buflen = 1024; - void *buffer = alloca (buflen); - bool buffer_use_malloc = false; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); gid_t *groups = *groupsp; @@ -67,26 +66,16 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, } struct group grp; - int res = _nss_files_parse_grent (line, &grp, buffer, buflen, errnop); + int res = _nss_files_parse_grent (line, &grp, + tmpbuf.data, tmpbuf.length, errnop); if (res == -1) { - size_t newbuflen = 2 * buflen; - if (buffer_use_malloc || ! __libc_use_alloca (buflen + newbuflen)) + if (!scratch_buffer_grow (&tmpbuf)) { - void *newbuf = realloc (buffer_use_malloc ? buffer : NULL, - newbuflen); - if (newbuf == NULL) - { - *errnop = ENOMEM; - status = NSS_STATUS_TRYAGAIN; - goto out; - } - buffer = newbuf; - buflen = newbuflen; - buffer_use_malloc = true; + *errnop = ENOMEM; + status = NSS_STATUS_TRYAGAIN; + goto out; } - else - buffer = extend_alloca (buffer, buflen, newbuflen); /* Reread current line, the parser has clobbered it. */ fsetpos (stream, &pos); continue; @@ -132,8 +121,7 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start, out: /* Free memory. */ - if (buffer_use_malloc) - free (buffer); + scratch_buffer_free (&tmpbuf); free (line); fclose (stream); |