From patchwork Sun Mar 1 18:09:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 5391 Received: (qmail 78190 invoked by alias); 2 Mar 2015 08:40:31 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 78125 invoked by uid 89); 2 Mar 2015 08:40:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, DATE_IN_PAST_12_24, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Message-Id: <886463585410f8c046babe912b326121f7a7c295.1425285061.git.fweimer@redhat.com> In-Reply-To: References: From: Florian Weimer Date: Sun, 1 Mar 2015 19:09:00 +0100 Subject: [PATCH 17/25] nss_files: Use struct scratch_buffer instead of extend_alloca To: libc-alpha@sourceware.org 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. --- nss/nss_files/files-hosts.c | 64 +++++++--------------------------------- 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 4c51c90..4fd492d 100644 --- a/nss/nss_files/files-hosts.c +++ b/nss/nss_files/files-hosts.c @@ -22,7 +22,7 @@ #include #include #include - +#include /* Get implementation for some internal functions. */ #include "../resolv/mapv4v6addr.h" @@ -149,15 +149,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; @@ -165,9 +162,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 (&tmp_result_buf, tmp_buffer, - tmp_buflen, errnop, herrnop, af, - flags)) + while ((status = internal_getent (&tmp_result_buf, + tmpbuf.data, tmpbuf.length, + errnop, herrnop, af, flags)) == NSS_STATUS_SUCCESS) { int matches = 1; @@ -291,54 +288,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); } if (! keep_stream) diff --git a/nss/nss_files/files-initgroups.c b/nss/nss_files/files-initgroups.c index 084d36b..abd2bc7 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 . */ -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include 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);