This is the mail archive of the libc-hacker@sources.redhat.com mailing list for the glibc project.

Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] __libc_alloca_cutoff (aka make mysql and others apps with very low RLIMIT_STACK setting happy)


Hi!

MySQL is using very low RLIMIT_STACK setting (or is it just too low
pthread_attr_setstacksize?) yet does gethostbyname from such threads
and thus crashes when external connections are made to it.
There is a lot of other places in glibc which use various hardcoded
constants to decide whether to use alloca or fall back to malloc.
The following patch deals with this by changing all
such hardcoded constants (I could find) to a variable and changes resolv
to also use malloc as fallback variant.
I haven't changed all setrlimit and getrlimit implementations yet (nor have
a nptl patch) plus did only limited testing so far, but e.g.

#include <netdb.h>
#include <pthread.h>

void *foo (void *arg)
{
  gethostbyname ("sources.redhat.com");
  return 0;
}

int main (void)
{
  pthread_attr_t a;
  pthread_t t;
  pthread_attr_init (&a);
  pthread_attr_setstacksize (&a, 16384);

  pthread_create (&t, &a, foo, 0);
  pthread_join (t, NULL);
}

or

#include <netdb.h>
#include <sys/resource.h>

void *foo (void *arg)
{
  gethostbyname ("sources.redhat.com");
  return 0;
}

int main (void)
{
  struct rlimit r;
  getrlimit (RLIMIT_STACK, &r);
  r.rlim_cur = 3*4096;
  setrlimit (RLIMIT_STACK, &r);
  foo (0);
}

work now and crashed before. Setting rlim_cur to 8192 and doing DNS lookup
still crashes, since res_init.c (but other places in glibc too) use
char buf[BUFSIZ];
on the stack.

2002-10-07  Jakub Jelinek  <jakub@redhat.com>

	* include/alloca.h (__libc_alloca_cutoff): New variable.
	(__libc_set_alloca_cutoff): New prototype.
	(__set_alloca_cutoff): New inline function.
	* malloc/Versions (libc: GLIBC_PRIVATE): Export __libc_alloca_cutoff
	and __libc_set_alloca_cutoff.
	* malloc/Makefile (routines): Add allocalim.
	* malloc/allocalim.c: New file.
	* resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r,
	_nss_dns_gethostbyaddr_r): Use alloca or malloc to allocate
	host_buffer depending on __libc_alloca_cutoff.
	* resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r,
	_nss_dns_getnetbyaddr_r): Use alloca or malloc to allocate
	net_buffer depending on __libc_alloca_cutoff.
	* resolv/res_query.c (res_nquery): Use alloca or malloc to allocate
	buf depending on __libc_alloca_cutoff.
	* resolv/gethnamaddr.c (gethostbyname2, gethostbyaddr): Likewise.
	* stdio-common/vfprintf.c (vfprintf): Use __libc_alloca_cutoff
	instead of hardcoded constants.
	* stdio-common/printf_fp.c (__printf_fp): Likewise.
	* string/strcoll.c (strcoll): Likewise.
	* string/strxfrm.c (strxfrm): Likewise.
	* sysdeps/posix/readv.c (__readv): Likewise.
	* sysdeps/posix/writev.c (__writev): Likewise.
	* sysdeps/unix/sysv/linux/i386/setrlimit.c (__new_setrlimit): Call
	__set_alloca_cutoff.
	* sysdeps/unix/sysv/linux/i386/getrlimit.c (__new_getrlimit):
	Likewise.

	* manager.c (__pthread_allocate_stack): Call __set_alloca_cutoff.

--- libc/include/alloca.h.jj	2002-09-30 16:45:04.000000000 +0200
+++ libc/include/alloca.h	2002-10-08 00:12:01.000000000 +0200
@@ -11,4 +11,16 @@ extern void *__alloca (size_t __size);
 # define __alloca(size)	__builtin_alloca (size)
 #endif /* GCC.  */
 
+extern size_t __libc_alloca_cutoff;
+libc_hidden_proto (__libc_alloca_cutoff)
+
+extern void __libc_set_alloca_cutoff (size_t size);
+libc_hidden_proto (__libc_set_alloca_cutoff)
+
+extern inline void __set_alloca_cutoff (size_t size)
+{
+  if (__libc_alloca_cutoff > size / 4)
+    __libc_set_alloca_cutoff (size / 4);
+}
+
 #endif
--- libc/linuxthreads/manager.c.jj	2002-08-28 12:58:03.000000000 +0200
+++ libc/linuxthreads/manager.c	2002-10-07 23:55:45.000000000 +0200
@@ -388,6 +388,7 @@ static int pthread_allocate_stack(const 
       /* Clear the thread data structure.  */
       memset (new_thread, '\0', sizeof (*new_thread));
 #endif
+      stacksize = attr->__stacksize;
     }
   else
     {
@@ -555,6 +556,7 @@ static int pthread_allocate_stack(const 
 # endif  /* !NEED_SEPARATE_REGISTER_STACK */
 #endif   /* !FLOATING_STACKS */
     }
+  __set_alloca_cutoff (stacksize);
   *out_new_thread = (char *) new_thread;
   *out_new_thread_bottom = new_thread_bottom;
   *out_guardaddr = guardaddr;
--- libc/malloc/Versions.jj	2000-04-18 08:13:14.000000000 +0200
+++ libc/malloc/Versions	2002-10-07 23:54:46.000000000 +0200
@@ -55,4 +55,7 @@ libc {
     # p*
     posix_memalign;
   }
+  GLIBC_PRIVATE {
+    __libc_alloca_cutoff; __libc_set_alloca_cutoff;
+  }
 }
--- libc/malloc/Makefile.jj	2002-09-20 08:48:09.000000000 +0200
+++ libc/malloc/Makefile	2002-10-07 14:28:48.000000000 +0200
@@ -36,7 +36,7 @@ distribute = thread-m.h mtrace.pl mcheck
 gmalloc-routines := malloc morecore
 # Things to include in the standalone distribution.
 dist-routines = $(gmalloc-routines) mcheck mtrace
-routines = $(dist-routines) obstack
+routines = $(dist-routines) obstack allocalim
 
 install-lib := libmcheck.a
 non-lib.a := libmcheck.a
--- libc/malloc/allocalim.c.jj	2002-10-07 14:28:54.000000000 +0200
+++ libc/malloc/allocalim.c	2002-10-08 00:12:20.000000000 +0200
@@ -0,0 +1,36 @@
+/* Alloca upper bound handling.
+   Copyright (C) 2002 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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <stdlib.h>
+#include <bits/libc-lock.h>
+
+/* Default alloca cutoff.  */
+size_t __libc_alloca_cutoff = 65536;
+libc_hidden_data_def (__libc_alloca_cutoff)
+
+__libc_lock_define_initialized (static, lock);
+
+void __libc_set_alloca_cutoff (size_t size)
+{
+  __libc_lock_lock (lock);
+  if (__libc_alloca_cutoff > size)
+    __libc_alloca_cutoff = size;
+  __libc_lock_unlock (lock);
+}
+libc_hidden_def (__libc_set_alloca_cutoff)
--- libc/resolv/nss_dns/dns-host.c.jj	2002-08-27 23:19:49.000000000 +0200
+++ libc/resolv/nss_dns/dns-host.c	2002-10-07 23:29:43.000000000 +0200
@@ -132,12 +132,13 @@ _nss_dns_gethostbyname2_r (const char *n
 			   char *buffer, size_t buflen, int *errnop,
 			   int *h_errnop)
 {
-  querybuf host_buffer;
+  querybuf *host_buffer;
   char tmp[NS_MAXDNAME];
   int size, type, n;
   const char *cp;
-  int map = 0;
+  int map = 0, use_malloc = 0;
   int olderr = errno;
+  enum nss_status status;
 
   if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
     return NSS_STATUS_UNAVAIL;
@@ -169,8 +170,21 @@ _nss_dns_gethostbyname2_r (const char *n
       && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL)
     name = cp;
 
-  n = res_nsearch (&_res, name, C_IN, type, host_buffer.buf,
-		   sizeof (host_buffer.buf));
+  if (__libc_alloca_cutoff < MAXPACKET)
+    {
+      host_buffer = (querybuf *) malloc (sizeof (querybuf));
+      if (host_buffer == NULL)
+	{
+	  *errnop = ENOMEM;
+	  return NSS_STATUS_UNAVAIL;
+	}
+      use_malloc = 1;
+    }
+  else
+    host_buffer = (querybuf *) alloca (sizeof (querybuf));
+
+  n = res_nsearch (&_res, name, C_IN, type, host_buffer->buf,
+		   sizeof (host_buffer->buf));
   if (n < 0)
     {
       enum nss_status status = (errno == ECONNREFUSED
@@ -185,11 +199,15 @@ _nss_dns_gethostbyname2_r (const char *n
 	 by having the RES_USE_INET6 bit in _res.options set, we try
 	 another lookup.  */
       if (af == AF_INET6 && (_res.options & RES_USE_INET6))
-	n = res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf,
-			 sizeof (host_buffer.buf));
+	n = res_nsearch (&_res, name, C_IN, T_A, host_buffer->buf,
+			 sizeof (host_buffer->buf));
 
       if (n < 0)
-	return status;
+	{
+	  if (use_malloc)
+	    free (host_buffer);
+	  return status;
+	}
 
       map = 1;
 
@@ -197,8 +215,11 @@ _nss_dns_gethostbyname2_r (const char *n
       result->h_length = INADDRSZ;;
     }
 
-  return getanswer_r (&host_buffer, n, name, type, result, buffer, buflen,
-		      errnop, h_errnop, map);
+  status = getanswer_r (host_buffer, n, name, type, result, buffer, buflen,
+			errnop, h_errnop, map);
+  if (use_malloc)
+    free (host_buffer);
+  return status;
 }
 
 
@@ -236,10 +257,10 @@ _nss_dns_gethostbyaddr_r (const void *ad
     char *h_addr_ptrs[MAX_NR_ADDRS + 1];
     char linebuffer[0];
   } *host_data = (struct host_data *) buffer;
-  querybuf host_buffer;
+  querybuf *host_buffer;
   char qbuf[MAXDNAME+1], *qp = NULL;
   size_t size;
-  int n, status;
+  int n, status, use_malloc = 0;
   int olderr = errno;
 
   if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
@@ -294,23 +315,40 @@ _nss_dns_gethostbyaddr_r (const void *ad
       break;
     }
 
-  n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
-		  sizeof host_buffer);
+  if (__libc_alloca_cutoff < MAXPACKET)
+    {
+      host_buffer = (querybuf *) malloc (sizeof (querybuf));
+      if (host_buffer == NULL)
+	{
+	  *errnop = ENOMEM;
+	  return NSS_STATUS_UNAVAIL;
+	}
+      use_malloc = 1;
+    }
+  else
+    host_buffer = (querybuf *) alloca (sizeof (querybuf));
+
+  n = res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer->buf,
+		  sizeof (host_buffer->buf));
   if (n < 0 && af == AF_INET6)
     {
       strcpy (qp, "ip6.int");
-      n = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *)host_buffer.buf,
-		      sizeof host_buffer);
+      n = res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer->buf,
+		      sizeof (host_buffer->buf));
     }
   if (n < 0)
     {
       *h_errnop = h_errno;
       __set_errno (olderr);
+      if (use_malloc)
+	free (host_buffer);
       return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     }
 
-  status = getanswer_r (&host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
+  status = getanswer_r (host_buffer, n, qbuf, T_PTR, result, buffer, buflen,
 			errnop, h_errnop, 0 /* XXX */);
+  if (use_malloc)
+    free (host_buffer);
   if (status != NSS_STATUS_SUCCESS)
     {
       *h_errnop = h_errno;
--- libc/resolv/nss_dns/dns-network.c.jj	2002-09-05 11:57:18.000000000 +0200
+++ libc/resolv/nss_dns/dns-network.c	2002-10-07 18:42:42.000000000 +0200
@@ -110,27 +110,47 @@ _nss_dns_getnetbyname_r (const char *nam
 			 int *herrnop)
 {
   /* Return entry for network with NAME.  */
-  querybuf net_buffer;
-  int anslen;
+  querybuf *net_buffer;
+  int anslen, use_malloc = 0;
   char *qbuf;
+  enum nss_status status;
 
   if ((_res.options & RES_INIT) == 0 && __res_ninit (&_res) == -1)
     return NSS_STATUS_UNAVAIL;
 
   qbuf = strdupa (name);
-  anslen = res_nsearch (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
-			sizeof (querybuf));
+
+  if (__libc_alloca_cutoff < MAXPACKET)
+    {
+      net_buffer = (querybuf *) malloc (sizeof (querybuf));
+      if (net_buffer == NULL)
+	{
+	  *errnop = ENOMEM;
+	  return NSS_STATUS_UNAVAIL;
+	}
+      use_malloc = 1;
+    }
+  else
+    net_buffer = (querybuf *) alloca (sizeof (querybuf));
+
+  anslen = res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer->buf,
+			sizeof (net_buffer->buf));
   if (anslen < 0)
     {
       /* Nothing found.  */
       *errnop = errno;
+      if (use_malloc)
+	free (net_buffer);
       return (errno == ECONNREFUSED
 	      || errno == EPFNOSUPPORT
 	      || errno == EAFNOSUPPORT)
 	? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     }
 
-  return getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYNAME);
+  status = getanswer_r (net_buffer, anslen, result, buffer, buflen, BYNAME);
+  if (use_malloc)
+    free (net_buffer);
+  return status;
 }
 
 
@@ -141,10 +161,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, i
 {
   /* Return entry for network with NAME.  */
   enum nss_status status;
-  querybuf net_buffer;
+  querybuf *net_buffer;
   unsigned int net_bytes[4];
   char qbuf[MAXDNAME];
-  int cnt, anslen;
+  int cnt, anslen, use_malloc = 0;
   u_int32_t net2;
   int olderr = errno;
 
@@ -181,20 +201,37 @@ _nss_dns_getnetbyaddr_r (uint32_t net, i
       break;
     }
 
-  anslen = res_nquery (&_res, qbuf, C_IN, T_PTR, (u_char *) &net_buffer,
-		       sizeof (querybuf));
+  if (__libc_alloca_cutoff < MAXPACKET)
+    {
+      net_buffer = (querybuf *) malloc (sizeof (querybuf));
+      if (net_buffer == NULL)
+	{
+	  *errnop = ENOMEM;
+	  return NSS_STATUS_UNAVAIL;
+	}
+      use_malloc = 1;
+    }
+  else
+    net_buffer = (querybuf *) alloca (sizeof (querybuf));
+
+  anslen = res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer->buf,
+		       sizeof (net_buffer->buf));
   if (anslen < 0)
     {
       /* Nothing found.  */
       int err = errno;
       __set_errno (olderr);
+      if (use_malloc)
+	free (net_buffer);
       return (err == ECONNREFUSED
 	      || err == EPFNOSUPPORT
 	      || err == EAFNOSUPPORT)
 	? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
     }
 
-  status = getanswer_r (&net_buffer, anslen, result, buffer, buflen, BYADDR);
+  status = getanswer_r (net_buffer, anslen, result, buffer, buflen, BYADDR);
+  if (use_malloc)
+    free (net_buffer);
   if (status == NSS_STATUS_SUCCESS)
     {
       /* Strip trailing zeros.  */
--- libc/resolv/res_query.c.jj	2002-08-27 23:19:49.000000000 +0200
+++ libc/resolv/res_query.c	2002-10-07 18:03:27.000000000 +0200
@@ -108,28 +108,42 @@ res_nquery(res_state statp,
 	   u_char *answer,	/* buffer to put answer */
 	   int anslen)		/* size of answer buffer */
 {
-	u_char buf[MAXPACKET];
+	u_char *buf;
 	HEADER *hp = (HEADER *) answer;
-	int n;
+	int n, use_malloc = 0;
 
 	hp->rcode = NOERROR;	/* default */
 
+	if (__libc_alloca_cutoff < MAXPACKET) {
+		buf = malloc (MAXPACKET);
+		if (buf == NULL) {
+			__set_h_errno (NETDB_INTERNAL);
+			return -1;
+		}
+		use_malloc = 1;
+	} else
+		buf = alloca (MAXPACKET);
+
 #ifdef DEBUG
 	if (statp->options & RES_DEBUG)
 		printf(";; res_query(%s, %d, %d)\n", name, class, type);
 #endif
 
 	n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
-			 buf, sizeof(buf));
+			 buf, MAXPACKET);
 	if (n <= 0) {
 #ifdef DEBUG
 		if (statp->options & RES_DEBUG)
 			printf(";; res_query: mkquery failed\n");
 #endif
 		RES_SET_H_ERRNO(statp, NO_RECOVERY);
+		if (use_malloc)
+			free (buf);
 		return (n);
 	}
 	n = res_nsend(statp, buf, n, answer, anslen);
+	if (use_malloc)
+		free (buf);
 	if (n < 0) {
 #ifdef DEBUG
 		if (statp->options & RES_DEBUG)
--- libc/resolv/gethnamaddr.c.jj	2002-09-25 11:11:53.000000000 +0200
+++ libc/resolv/gethnamaddr.c	2002-10-07 23:23:52.000000000 +0200
@@ -510,10 +510,11 @@ gethostbyname2(name, af)
 	const char *name;
 	int af;
 {
-	querybuf buf;
+	querybuf *buf;
 	register const char *cp;
 	char *bp;
-	int n, size, type, len;
+	int n, size, type, len, use_malloc = 0;
+	struct hostent *ret;
 	extern struct hostent *_gethtbyname2();
 
 	if ((_res.options & RES_INIT) == 0 && __res_ninit(&_res) == -1) {
@@ -615,13 +616,26 @@ gethostbyname2(name, af)
 				break;
 		}
 
-	if ((n = res_nsearch(&_res, name, C_IN, type, buf.buf, sizeof(buf.buf))) < 0) {
+	if (__libc_alloca_cutoff < MAXPACKET) {
+		buf = (querybuf *) malloc (sizeof (*buf));
+		if (buf == NULL) {
+			__set_h_errno (NETDB_INTERNAL);
+			return NULL;
+		}
+		use_malloc = 1;
+	} else
+		buf = (querybuf *) alloca (sizeof (*buf));
+
+	if ((n = res_nsearch(&_res, name, C_IN, type, buf->buf, sizeof(buf->buf))) < 0) {
 		dprintf("res_nsearch failed (%d)\n", n);
 		if (errno == ECONNREFUSED)
 			return (_gethtbyname2(name, af));
 		return (NULL);
 	}
-	return (getanswer(&buf, n, name, type));
+	ret = getanswer(buf, n, name, type);
+	if (use_malloc)
+		free (buf);
+	return ret;
 }
 
 struct hostent *
@@ -633,9 +647,9 @@ gethostbyaddr(addr, len, af)
 	const u_char *uaddr = (const u_char *)addr;
 	static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
 	static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 };
-	int n;
+	int n, use_malloc = 0;
 	socklen_t size;
-	querybuf buf;
+	querybuf *buf;
 	register struct hostent *hp;
 	char qbuf[MAXDNAME+1], *qp = NULL;
 #ifdef SUNSECURITY
@@ -696,18 +710,34 @@ gethostbyaddr(addr, len, af)
 	default:
 		abort();
 	}
-	n = res_nquery(&_res, qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+
+	if (__libc_alloca_cutoff < MAXPACKET) {
+		buf = (querybuf *) malloc (sizeof (*buf));
+		if (buf == NULL) {
+			__set_h_errno (NETDB_INTERNAL);
+			return NULL;
+		}
+		use_malloc = 1;
+	} else
+		buf = (querybuf *) alloca (sizeof (*buf));
+
+	n = res_nquery(&_res, qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf);
 	if (n < 0 && af == AF_INET6) {
 		strcpy(qp, "ip6.int");
-		n = res_nquery(&_res, qbuf, C_IN, T_PTR, (u_char *)buf.buf, sizeof buf.buf);
+		n = res_nquery(&_res, qbuf, C_IN, T_PTR, buf->buf, sizeof buf->buf);
 	}
 	if (n < 0) {
+		if (use_malloc)
+			free (buf);
 		dprintf("res_nquery failed (%d)\n", n);
 		if (errno == ECONNREFUSED)
 			return (_gethtbyaddr(addr, len, af));
 		return (NULL);
 	}
-	if (!(hp = getanswer(&buf, n, qbuf, T_PTR)))
+	hp = getanswer(buf, n, qbuf, T_PTR);
+	if (use_malloc)
+		free (buf);
+	if (!hp)
 		return (NULL);	/* h_errno was set by getanswer() */
 #ifdef SUNSECURITY
 	if (af == AF_INET) {
--- libc/stdio-common/vfprintf.c.jj	2002-09-30 16:45:06.000000000 +0200
+++ libc/stdio-common/vfprintf.c	2002-10-07 14:21:46.000000000 +0200
@@ -1039,7 +1039,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 									      \
 	    /* Allocate dynamically an array which definitely is long	      \
 	       enough for the wide character version.  */		      \
-	    if (len < 8192)						      \
+	    if (len <= __libc_alloca_cutoff)				      \
 	      string = (CHAR_T *) alloca (len * sizeof (wchar_t));	      \
 	    else if ((string = (CHAR_T *) malloc (len * sizeof (wchar_t)))    \
 		     == NULL)						      \
@@ -1201,7 +1201,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 	    if (prec >= 0)						      \
 	      {								      \
 		/* The string `s2' might not be NUL terminated.  */	      \
-		if (prec < 32768)					      \
+		if (prec <= __libc_alloca_cutoff)			      \
 		  string = (char *) alloca (prec);			      \
 		else if ((string = (char *) malloc (prec)) == NULL)	      \
 		  {							      \
@@ -1219,7 +1219,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 		  {							      \
 		    assert (__mbsinit (&mbstate));			      \
 		    s2 = (const wchar_t *) string;			      \
-		    if (len + 1 < 32768)				      \
+		    if (len + 1 < __libc_alloca_cutoff)			      \
 		      string = (char *) alloca (len + 1);		      \
 		    else if ((string = (char *) malloc (len + 1)) == NULL)    \
 		      {							      \
@@ -1448,7 +1448,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 	  {
 	    /* We have to use a special buffer.  The "32" is just a safe
 	       bet for all the output which is not counted in the width.  */
-	    if (width < (int) (32768 / sizeof (CHAR_T)))
+	    if (width <= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	      workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
 			 + (width + 32));
 	    else
@@ -1473,7 +1473,7 @@ vfprintf (FILE *s, const CHAR_T *format,
 	{
 	  /* We have to use a special buffer.  The "32" is just a safe
 	     bet for all the output which is not counted in the width.  */
-	  if (width < (int) (32768 / sizeof (CHAR_T)))
+	  if (width <= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	    workend = ((CHAR_T *) alloca ((width + 32) * sizeof (CHAR_T))
 		       + (width + 32));
 	  else
@@ -1516,7 +1516,7 @@ vfprintf (FILE *s, const CHAR_T *format,
       if (prec > width
 	  && prec + 32 > (int)(sizeof (work_buffer) / sizeof (work_buffer[0])))
 	{
-	  if (prec < (int) (32768 / sizeof (CHAR_T)))
+	  if (prec <= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	    workend = alloca (prec + 32) + (prec + 32);
 	  else
 	    {
@@ -1832,7 +1832,8 @@ do_positional:
 	if (MAX (prec, width) + 32 > (int) (sizeof (work_buffer)
 					    / sizeof (CHAR_T)))
 	  {
-	    if (MAX (prec, width) < (int) (32768 / sizeof (CHAR_T)))
+	    if (MAX (prec, width)
+		<= (int) (__libc_alloca_cutoff / sizeof (CHAR_T)))
 	      workend = ((CHAR_T *) alloca ((MAX (prec, width) + 32)
 					    * sizeof (CHAR_T))
 			 + (MAX (prec, width) + 32));
--- libc/stdio-common/printf_fp.c.jj	2002-10-02 10:26:33.000000000 +0200
+++ libc/stdio-common/printf_fp.c	2002-10-07 14:21:46.000000000 +0200
@@ -869,7 +869,8 @@ __printf_fp (FILE *fp,
        it is possible that we need two more characters in front of all the
        other output.  If the amount of memory we have to allocate is too
        large use `malloc' instead of `alloca'.  */
-    buffer_malloced = chars_needed > 5000;
+    buffer_malloced
+      = chars_needed > __libc_alloca_cutoff / 2 / sizeof (wchar_t);
     if (buffer_malloced)
       {
 	wbuffer = (wchar_t *) malloc ((2 + chars_needed) * sizeof (wchar_t));
--- libc/string/strcoll.c.jj	2002-09-30 16:45:06.000000000 +0200
+++ libc/string/strcoll.c	2002-10-07 14:21:46.000000000 +0200
@@ -155,7 +155,7 @@ STRCOLL (s1, s2, l)
 
      Please note that the localedef programs makes sure that `position'
      is not used at the first level.  */
-  if (s1len + s2len >= 16384)
+  if (s1len + s2len > __libc_alloca_cutoff)
     {
       idx1arr = (int32_t *) malloc ((s1len + s2len) * (sizeof (int32_t) + 1));
       idx2arr = &idx1arr[s1len];
--- libc/string/strxfrm.c.jj	2002-09-30 16:45:06.000000000 +0200
+++ libc/string/strxfrm.c	2002-10-07 14:21:46.000000000 +0200
@@ -175,7 +175,7 @@ STRXFRM (STRING_TYPE *dest, const STRING
      values.  But since there is no limit on the length of the string
      we have to use `malloc' if the string is too long.  We should be
      very conservative here.  */
-  if (srclen >= 16384)
+  if (srclen > __libc_alloca_cutoff)
     {
       idxarr = (int32_t *) malloc ((srclen + 1) * (sizeof (int32_t) + 1));
       rulearr = (unsigned char *) &idxarr[srclen];
--- libc/sysdeps/posix/readv.c.jj	2002-09-30 16:45:08.000000000 +0200
+++ libc/sysdeps/posix/readv.c	2002-10-07 14:21:46.000000000 +0200
@@ -55,8 +55,8 @@ __readv (int fd, const struct iovec *vec
   /* Allocate a temporary buffer to hold the data.  We should normally
      use alloca since it's faster and does not require synchronization
      with other threads.  But we cannot if the amount of memory
-     required is too large.  Use 512k as the limit.  */
-  if (bytes < 512 * 1024)
+     required is too large.  */
+  if (bytes <= __libc_alloca_cutoff)
     buffer = (char *) __alloca (bytes);
   else
     {
--- libc/sysdeps/posix/writev.c.jj	2002-09-30 16:45:08.000000000 +0200
+++ libc/sysdeps/posix/writev.c	2002-10-07 14:21:46.000000000 +0200
@@ -55,8 +55,8 @@ __writev (int fd, const struct iovec *ve
   /* Allocate a temporary buffer to hold the data.  We should normally
      use alloca since it's faster and does not require synchronization
      with other threads.  But we cannot if the amount of memory
-     required is too large.  Use 512k as the limit.  */
-  if (bytes < 512 * 1024)
+     required is too large.  */
+  if (bytes <= __libc_alloca_cutoff)
     buffer = (char *) __alloca (bytes);
   else
     {
--- libc/sysdeps/unix/sysv/linux/i386/setrlimit.c.jj	2001-08-23 18:50:59.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/i386/setrlimit.c	2002-10-08 00:32:58.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 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
@@ -24,6 +24,7 @@
 #include <sys/syscall.h>
 #include <shlib-compat.h>
 #include <bp-checks.h>
+#include <alloca.h>
 
 #include "kernel-features.h"
 
@@ -43,6 +44,9 @@ extern int __have_no_new_getrlimit; /* f
 int
 __new_setrlimit (enum __rlimit_resource resource, const struct rlimit *rlimits)
 {
+  if (__builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
+
 #ifdef __ASSUME_NEW_GETRLIMIT_SYSCALL
   return INLINE_SYSCALL (setrlimit, 2, resource, CHECK_1 (rlimits));
 #else
--- libc/sysdeps/unix/sysv/linux/i386/getrlimit.c.jj	2001-08-23 18:50:54.000000000 +0200
+++ libc/sysdeps/unix/sysv/linux/i386/getrlimit.c	2002-10-08 00:32:49.000000000 +0200
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2000, 2002 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
@@ -44,10 +44,15 @@ int __have_no_new_getrlimit;
 int
 __new_getrlimit (enum __rlimit_resource resource, struct rlimit *rlimits)
 {
+  int result;
 #ifdef __ASSUME_NEW_GETRLIMIT_SYSCALL
-  return INLINE_SYSCALL (ugetrlimit, 2, resource, CHECK_1 (rlimits));
+  result = INLINE_SYSCALL (ugetrlimit, 2, resource, CHECK_1 (rlimits));
+
+  if (__builtin_expect (result != -1, 1)
+      && __builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
+  return result;
 #else
-  int result;
 
 # ifdef __NR_ugetrlimit
   if (__have_no_new_getrlimit <= 0)
@@ -57,6 +62,9 @@ __new_getrlimit (enum __rlimit_resource 
       /* If the system call is available remember this fact and return.  */
       if (result != -1 || errno != ENOSYS)
 	{
+	  if (__builtin_expect (result != -1, 1)
+	      && __builtin_expect (resource == RLIMIT_STACK, 0))
+	    __set_alloca_cutoff (rlimits->rlim_cur);
 	  __have_no_new_getrlimit = -1;
 	  return result;
 	}
@@ -79,6 +87,8 @@ __new_getrlimit (enum __rlimit_resource 
   if (rlimits->rlim_max == RLIM_INFINITY >> 1)
     rlimits->rlim_max = RLIM_INFINITY;
 
+  if (__builtin_expect (resource == RLIMIT_STACK, 0))
+    __set_alloca_cutoff (rlimits->rlim_cur);
   return result;
 #endif
 }

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]