From ac631cbe7021105c7fb8438deaeef66fe544b9aa Mon Sep 17 00:00:00 2001
From: Aldy Hernandez <aldyh@redhat.com>
Date: Fri, 29 Jul 2016 16:40:55 +0000
Subject: [PATCH] libiberty.h (MAX_ALLOCA_SIZE): New macro.

include/
	* libiberty.h (MAX_ALLOCA_SIZE): New macro.

libiberty/
	* make-relative-prefix.c (make_relative_prefix_1): Fall back to
	malloc if alloca argument is greater than MAX_ALLOCA_SIZE.

From-SVN: r238880
---
 include/ChangeLog                |  4 ++++
 include/libiberty.h              | 11 +++++++++++
 libiberty/ChangeLog              |  5 +++++
 libiberty/make-relative-prefix.c | 11 ++++++++---
 4 files changed, 28 insertions(+), 3 deletions(-)

diff --git a/include/ChangeLog b/include/ChangeLog
index 8b46056ce312..06be0281e26c 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,7 @@
+2016-07-29  Aldy Hernandez  <aldyh@redhat.com>
+
+	* libiberty.h (MAX_ALLOCA_SIZE): New macro.
+
 2016-05-26  Chung-Lin Tang  <cltang@codesourcery.com>
 
 	* gomp-constants.h (GOMP_VERSION): Increment to 1, add comment to
diff --git a/include/libiberty.h b/include/libiberty.h
index a9c885fc6704..605ff56abd8f 100644
--- a/include/libiberty.h
+++ b/include/libiberty.h
@@ -397,6 +397,17 @@ extern void hex_init (void);
 /* Save files used for communication between processes.  */
 #define PEX_SAVE_TEMPS		0x4
 
+/* Max number of alloca bytes per call before we must switch to malloc.
+
+   ?? Swiped from gnulib's regex_internal.h header.  Is this actually
+   the case?  This number seems arbitrary, though sane.
+
+   The OS usually guarantees only one guard page at the bottom of the stack,
+   and a page size can be as small as 4096 bytes.  So we cannot safely
+   allocate anything larger than 4096 bytes.  Also care for the possibility
+   of a few compiler-allocated temporary stack slots.  */
+#define MAX_ALLOCA_SIZE	4032
+
 /* Prepare to execute one or more programs, with standard output of
    each program fed to standard input of the next.
    FLAGS	As above.
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index 6209195ab38b..a2e49a12cea8 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,8 @@
+2016-07-29  Aldy Hernandez  <aldyh@redhat.com>
+
+	* make-relative-prefix.c (make_relative_prefix_1): Fall back to
+	malloc if alloca argument is greater than MAX_ALLOCA_SIZE.
+
 2016-07-15  Jason Merrill  <jason@redhat.com>
 
 	* cp-demangle.c (cplus_demangle_operators): Add f[lrLR].
diff --git a/libiberty/make-relative-prefix.c b/libiberty/make-relative-prefix.c
index fe639d18bd28..fa813998be3e 100644
--- a/libiberty/make-relative-prefix.c
+++ b/libiberty/make-relative-prefix.c
@@ -233,6 +233,7 @@ make_relative_prefix_1 (const char *progname, const char *bin_prefix,
   int i, n, common;
   int needed_len;
   char *ret = NULL, *ptr, *full_progname;
+  char *alloc_ptr = NULL;
 
   if (progname == NULL || bin_prefix == NULL || prefix == NULL)
     return NULL;
@@ -256,7 +257,10 @@ make_relative_prefix_1 (const char *progname, const char *bin_prefix,
 #ifdef HAVE_HOST_EXECUTABLE_SUFFIX
 	  len += strlen (HOST_EXECUTABLE_SUFFIX);
 #endif
-	  nstore = (char *) alloca (len);
+	  if (len < MAX_ALLOCA_SIZE)
+	    nstore = (char *) alloca (len);
+	  else
+	    alloc_ptr = nstore = (char *) malloc (len);
 
 	  startp = endp = temp;
 	  while (1)
@@ -312,12 +316,12 @@ make_relative_prefix_1 (const char *progname, const char *bin_prefix,
   else
     full_progname = strdup (progname);
   if (full_progname == NULL)
-    return NULL;
+    goto bailout;
 
   prog_dirs = split_directories (full_progname, &prog_num);
   free (full_progname);
   if (prog_dirs == NULL)
-    return NULL;
+    goto bailout;
 
   bin_dirs = split_directories (bin_prefix, &bin_num);
   if (bin_dirs == NULL)
@@ -395,6 +399,7 @@ make_relative_prefix_1 (const char *progname, const char *bin_prefix,
   free_split_directories (prog_dirs);
   free_split_directories (bin_dirs);
   free_split_directories (prefix_dirs);
+  free (alloc_ptr);
 
   return ret;
 }
-- 
GitLab