aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-03-24 22:40:29 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-03-24 22:40:29 +0000
commit8899a2aba92c4a17f422172e7c9dd0e383eefa39 (patch)
treeaea400d25b0e9c32b84004728c995cd53ab33533 /src/backend/tcop/postgres.c
parenta09b9a36d3cc8e4c5cd2877b2b764dc14a78f58e (diff)
downloadpostgresql-8899a2aba92c4a17f422172e7c9dd0e383eefa39.tar.gz
postgresql-8899a2aba92c4a17f422172e7c9dd0e383eefa39.zip
Replace max_expr_depth parameter with a max_stack_depth parameter that
is measured in kilobytes and checked against actual physical execution stack depth, as per my proposal of 30-Dec. This gives us a fairly bulletproof defense against crashing due to runaway recursive functions.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 91442d49e6e..ff0ac6aa64a 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.396 2004/03/21 22:29:11 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.397 2004/03/24 22:40:29 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@@ -92,11 +92,22 @@ bool Log_disconnections = false;
*/
int XfuncMode = 0;
+/* GUC variable for maximum stack depth (measured in kilobytes) */
+int max_stack_depth = 2048;
+
+
/* ----------------
* private variables
* ----------------
*/
+/* max_stack_depth converted to bytes for speed of checking */
+static int max_stack_depth_bytes = 2048*1024;
+
+/* stack base pointer (initialized by PostgresMain) */
+static char *stack_base_ptr = NULL;
+
+
/*
* Flag to mark SIGHUP. Whenever the main loop comes around it
* will reread the configuration file. (Better than doing the
@@ -1970,6 +1981,64 @@ ProcessInterrupts(void)
}
+/*
+ * check_stack_depth: check for excessively deep recursion
+ *
+ * This should be called someplace in any recursive routine that might possibly
+ * recurse deep enough to overflow the stack. Most Unixen treat stack
+ * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
+ * before hitting the hardware limit. Unfortunately we have no direct way
+ * to detect the hardware limit, so we have to rely on the admin to set a
+ * GUC variable for it ...
+ */
+void
+check_stack_depth(void)
+{
+ char stack_top_loc;
+ int stack_depth;
+
+ /*
+ * Compute distance from PostgresMain's local variables to my own
+ *
+ * Note: in theory stack_depth should be ptrdiff_t or some such, but
+ * since the whole point of this code is to bound the value to something
+ * much less than integer-sized, int should work fine.
+ */
+ stack_depth = (int) (stack_base_ptr - &stack_top_loc);
+ /*
+ * Take abs value, since stacks grow up on some machines, down on others
+ */
+ if (stack_depth < 0)
+ stack_depth = -stack_depth;
+ /*
+ * Trouble?
+ *
+ * The test on stack_base_ptr prevents us from erroring out if called
+ * during process setup or in a non-backend process. Logically it should
+ * be done first, but putting it here avoids wasting cycles during normal
+ * cases.
+ */
+ if (stack_depth > max_stack_depth_bytes &&
+ stack_base_ptr != NULL)
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
+ errmsg("stack depth limit exceeded"),
+ errhint("Increase the configuration parameter \"max_stack_depth\".")));
+ }
+}
+
+/* GUC assign hook to update max_stack_depth_bytes from max_stack_depth */
+bool
+assign_max_stack_depth(int newval, bool doit, GucSource source)
+{
+ /* Range check was already handled by guc.c */
+ if (doit)
+ max_stack_depth_bytes = newval * 1024;
+ return true;
+}
+
+
static void
usage(char *progname)
{
@@ -2030,6 +2099,7 @@ PostgresMain(int argc, char *argv[], const char *username)
GucSource gucsource;
char *tmp;
int firstchar;
+ char stack_base;
StringInfoData input_message;
volatile bool send_rfq = true;
@@ -2069,6 +2139,9 @@ PostgresMain(int argc, char *argv[], const char *username)
SetProcessingMode(InitProcessing);
+ /* Set up reference point for stack depth checking */
+ stack_base_ptr = &stack_base;
+
/*
* Set default values for command-line options.
*/