summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2015-03-01 19:09:00 +0100
committerFlorian Weimer <fweimer@redhat.com>2016-04-25 06:19:30 +0200
commite970ea40df40ab5da24c984a0612f98a798221d8 (patch)
tree9875826fe8e52373f3a478ccdbbb569c6369002d
parent34ddffb50c2d2159c152cc34516f4c4088b3cc36 (diff)
downloadglibc-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.c64
-rw-r--r--nss/nss_files/files-initgroups.c32
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);