|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.396 2004/03/21 22:29:11 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.397 2004/03/24 22:40:29 tgl Exp $ |
12 | 12 | *
|
13 | 13 | * NOTES
|
14 | 14 | * this is the "main" module of the postgres backend and
|
@@ -92,11 +92,22 @@ bool Log_disconnections = false;
|
92 | 92 | */
|
93 | 93 | int XfuncMode = 0;
|
94 | 94 |
|
| 95 | +/* GUC variable for maximum stack depth (measured in kilobytes) */ |
| 96 | +int max_stack_depth = 2048; |
| 97 | + |
| 98 | + |
95 | 99 | /* ----------------
|
96 | 100 | * private variables
|
97 | 101 | * ----------------
|
98 | 102 | */
|
99 | 103 |
|
| 104 | +/* max_stack_depth converted to bytes for speed of checking */ |
| 105 | +static int max_stack_depth_bytes = 2048*1024; |
| 106 | + |
| 107 | +/* stack base pointer (initialized by PostgresMain) */ |
| 108 | +static char *stack_base_ptr = NULL; |
| 109 | + |
| 110 | + |
100 | 111 | /*
|
101 | 112 | * Flag to mark SIGHUP. Whenever the main loop comes around it
|
102 | 113 | * will reread the configuration file. (Better than doing the
|
@@ -1970,6 +1981,64 @@ ProcessInterrupts(void)
|
1970 | 1981 | }
|
1971 | 1982 |
|
1972 | 1983 |
|
| 1984 | +/* |
| 1985 | + * check_stack_depth: check for excessively deep recursion |
| 1986 | + * |
| 1987 | + * This should be called someplace in any recursive routine that might possibly |
| 1988 | + * recurse deep enough to overflow the stack. Most Unixen treat stack |
| 1989 | + * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves |
| 1990 | + * before hitting the hardware limit. Unfortunately we have no direct way |
| 1991 | + * to detect the hardware limit, so we have to rely on the admin to set a |
| 1992 | + * GUC variable for it ... |
| 1993 | + */ |
| 1994 | +void |
| 1995 | +check_stack_depth(void) |
| 1996 | +{ |
| 1997 | + char stack_top_loc; |
| 1998 | + int stack_depth; |
| 1999 | + |
| 2000 | + /* |
| 2001 | + * Compute distance from PostgresMain's local variables to my own |
| 2002 | + * |
| 2003 | + * Note: in theory stack_depth should be ptrdiff_t or some such, but |
| 2004 | + * since the whole point of this code is to bound the value to something |
| 2005 | + * much less than integer-sized, int should work fine. |
| 2006 | + */ |
| 2007 | + stack_depth = (int) (stack_base_ptr - &stack_top_loc); |
| 2008 | + /* |
| 2009 | + * Take abs value, since stacks grow up on some machines, down on others |
| 2010 | + */ |
| 2011 | + if (stack_depth < 0) |
| 2012 | + stack_depth = -stack_depth; |
| 2013 | + /* |
| 2014 | + * Trouble? |
| 2015 | + * |
| 2016 | + * The test on stack_base_ptr prevents us from erroring out if called |
| 2017 | + * during process setup or in a non-backend process. Logically it should |
| 2018 | + * be done first, but putting it here avoids wasting cycles during normal |
| 2019 | + * cases. |
| 2020 | + */ |
| 2021 | + if (stack_depth > max_stack_depth_bytes && |
| 2022 | + stack_base_ptr != NULL) |
| 2023 | + { |
| 2024 | + ereport(ERROR, |
| 2025 | + (errcode(ERRCODE_STATEMENT_TOO_COMPLEX), |
| 2026 | + errmsg("stack depth limit exceeded"), |
| 2027 | + errhint("Increase the configuration parameter \"max_stack_depth\"."))); |
| 2028 | + } |
| 2029 | +} |
| 2030 | + |
| 2031 | +/* GUC assign hook to update max_stack_depth_bytes from max_stack_depth */ |
| 2032 | +bool |
| 2033 | +assign_max_stack_depth(int newval, bool doit, GucSource source) |
| 2034 | +{ |
| 2035 | + /* Range check was already handled by guc.c */ |
| 2036 | + if (doit) |
| 2037 | + max_stack_depth_bytes = newval * 1024; |
| 2038 | + return true; |
| 2039 | +} |
| 2040 | + |
| 2041 | + |
1973 | 2042 | static void
|
1974 | 2043 | usage(char *progname)
|
1975 | 2044 | {
|
@@ -2030,6 +2099,7 @@ PostgresMain(int argc, char *argv[], const char *username)
|
2030 | 2099 | GucSource gucsource;
|
2031 | 2100 | char *tmp;
|
2032 | 2101 | int firstchar;
|
| 2102 | + char stack_base; |
2033 | 2103 | StringInfoData input_message;
|
2034 | 2104 | volatile bool send_rfq = true;
|
2035 | 2105 |
|
@@ -2069,6 +2139,9 @@ PostgresMain(int argc, char *argv[], const char *username)
|
2069 | 2139 |
|
2070 | 2140 | SetProcessingMode(InitProcessing);
|
2071 | 2141 |
|
| 2142 | + /* Set up reference point for stack depth checking */ |
| 2143 | + stack_base_ptr = &stack_base; |
| 2144 | + |
2072 | 2145 | /*
|
2073 | 2146 | * Set default values for command-line options.
|
2074 | 2147 | */
|
|
0 commit comments