[Top][All Lists]
[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
- PATCH: stack overflow on large dependency set,
Wil Evers <=