bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

PATCH: stack overflow on large dependency set


From: Wil Evers
Subject: PATCH: stack overflow on large dependency set
Date: Wed, 09 Oct 2002 15:57:10 +0200

Hi,

The attached patch against make-3.80 fixes a mysterious segfault that
occurred when I tried to regenerate a file that dependend on a lot of
other files.  

The total length of these prerequisite filenames was somewhat more than
1MB.  As it turns out, the use of alloca() for such a large data set in
the function set_file_variables() caused a stack overflow.  This is also
because on my Linux system, make is implicitly linked against
libpthread, which means that the maximum stacksize per thread is limited
to 2MB.

(A similar patch against make-3.79.1 is available on request.)

Thanks,

- Wil
Wil Evers, DOOSYS R&D, Utrecht, Holland
*** make-3.80/commands.c        Tue Oct  8 16:50:51 2002
--- make/commands.c     Wed Oct  9 12:38:16 2002
***************
*** 35,40 ****
--- 35,45 ----
  #ifndef       HAVE_UNISTD_H
  extern int getpid ();
  #endif
+ 
+ #define       PLUS_BUF_SIZE   0x10000
+ #define       QMARK_BUF_SIZE  0x10000
+ #define       BAR_BUF_SIZE    0x10000
+ 
  
  /* Set FILE's automatic variables up.  */
  
***************
*** 128,136 ****
--- 133,144 ----
  
    {
      unsigned int qmark_len, plus_len, bar_len;
+     char plus_buf[PLUS_BUF_SIZE];
      char *caret_value, *plus_value;
      char *cp;
+     char qmark_buf[QMARK_BUF_SIZE];
      char *qmark_value;
+     char bar_buf[BAR_BUF_SIZE];
      char *bar_value;
      char *qp;
      char *bp;
***************
*** 147,153 ****
      if (plus_len == 0)
        plus_len++;
  
!     cp = plus_value = (char *) alloca (plus_len);
  
      qmark_len = plus_len + 1; /* Will be this or less.  */
      for (d = file->deps; d != 0; d = d->next)
--- 155,166 ----
      if (plus_len == 0)
        plus_len++;
  
!     if (plus_len <= PLUS_BUF_SIZE) {
!       plus_value = plus_buf;
!     } else {
!       plus_value = (char *) xmalloc(plus_len);
!     }
!     cp = plus_value;
  
      qmark_len = plus_len + 1; /* Will be this or less.  */
      for (d = file->deps; d != 0; d = d->next)
***************
*** 193,200 ****
      /* Compute the values for $^, $?, and $|.  */
  
      cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */
!     qp = qmark_value = (char *) alloca (qmark_len);
!     bp = bar_value = (char *) alloca (bar_len);
  
      for (d = file->deps; d != 0; d = d->next)
        {
--- 206,225 ----
      /* Compute the values for $^, $?, and $|.  */
  
      cp = caret_value = plus_value; /* Reuse the buffer; it's big enough.  */
! 
!     if (qmark_len <= QMARK_BUF_SIZE) {
!       qmark_value = qmark_buf;
!     } else {
!       qmark_value = (char *) xmalloc(qmark_len);
!     }
!     qp = qmark_value;
! 
!     if (bar_len <= BAR_BUF_SIZE) {
!       bar_value = bar_buf;
!     } else {
!       bar_value = (char *) xmalloc(bar_len);
!     }
!     bp = bar_value;
  
      for (d = file->deps; d != 0; d = d->next)
        {
***************
*** 240,245 ****
--- 265,280 ----
  
      bp[bp > bar_value ? -1 : 0] = '\0';
      DEFINE_VARIABLE ("|", 1, bar_value);
+ 
+     if (bar_value != bar_buf) {
+       free(bar_value);
+     }
+     if (qmark_value != qmark_buf) {
+       free(qmark_value);
+     }
+     if (plus_value != plus_buf) {
+       free(plus_value);
+     }
    }
  
  #undef        DEFINE_VARIABLE

reply via email to

[Prev in Thread] Current Thread [Next in Thread]