summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/commands/variable.c48
-rw-r--r--src/backend/parser/parse_expr.c34
-rw-r--r--src/backend/parser/parser.c5
3 files changed, 84 insertions, 3 deletions
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 81c1e10bbd..482b9a23ae 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.31 2000/02/27 21:10:41 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.32 2000/03/17 05:29:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -25,6 +25,7 @@
#include "miscadmin.h"
#include "optimizer/cost.h"
#include "optimizer/paths.h"
+#include "parser/parse_expr.h"
#include "utils/builtins.h"
#include "utils/tqual.h"
#include "utils/trace.h"
@@ -86,6 +87,9 @@ static bool parse_geqo(char *);
static bool show_ksqo(void);
static bool reset_ksqo(void);
static bool parse_ksqo(char *);
+static bool reset_max_expr_depth(void);
+static bool show_max_expr_depth(void);
+static bool parse_max_expr_depth(char *);
static bool show_XactIsoLevel(void);
static bool reset_XactIsoLevel(void);
static bool parse_XactIsoLevel(char *);
@@ -935,6 +939,44 @@ reset_ksqo()
return TRUE;
}
+/*
+ * MAX_EXPR_DEPTH
+ */
+static bool
+parse_max_expr_depth(char *value)
+{
+ int newval;
+
+ if (value == NULL)
+ {
+ reset_max_expr_depth();
+ return TRUE;
+ }
+
+ newval = pg_atoi(value, sizeof(int), '\0');
+
+ if (newval < 10) /* somewhat arbitrary limit */
+ elog(ERROR, "Bad value for MAX_EXPR_DEPTH (%s)", value);
+
+ max_expr_depth = newval;
+
+ return TRUE;
+}
+
+static bool
+show_max_expr_depth()
+{
+ elog(NOTICE, "MAX_EXPR_DEPTH is %d", max_expr_depth);
+ return TRUE;
+}
+
+static bool
+reset_max_expr_depth(void)
+{
+ max_expr_depth = DEFAULT_MAX_EXPR_DEPTH;
+ return TRUE;
+}
+
/* SET TRANSACTION */
static bool
@@ -1104,6 +1146,10 @@ static struct VariableParsers
"ksqo", parse_ksqo, show_ksqo, reset_ksqo
},
{
+ "max_expr_depth", parse_max_expr_depth,
+ show_max_expr_depth, reset_max_expr_depth
+ },
+ {
"XactIsoLevel", parse_XactIsoLevel, show_XactIsoLevel, reset_XactIsoLevel
},
{
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index e2e297cb6b..419ad4d6d2 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.73 2000/03/14 23:06:32 thomas Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_expr.c,v 1.74 2000/03/17 05:29:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -32,6 +32,11 @@
#include "utils/builtins.h"
#include "utils/syscache.h"
+
+int max_expr_depth = DEFAULT_MAX_EXPR_DEPTH;
+
+static int expr_depth_counter = 0;
+
static Node *parser_typecast_constant(Value *expr, TypeName *typename);
static Node *parser_typecast_expression(ParseState *pstate,
Node *expr, TypeName *typename);
@@ -40,6 +45,20 @@ static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
static Node *transformIndirection(ParseState *pstate, Node *basenode,
List *indirection);
+
+/*
+ * Initialize for parsing a new query.
+ *
+ * We reset the expression depth counter here, in case it was left nonzero
+ * due to elog()'ing out of the last parsing operation.
+ */
+void
+parse_expr_init(void)
+{
+ expr_depth_counter = 0;
+}
+
+
/*
* transformExpr -
* analyze and transform expressions. Type checking and type casting is
@@ -55,6 +74,17 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
if (expr == NULL)
return NULL;
+ /*
+ * Guard against an overly complex expression leading to coredump
+ * due to stack overflow here, or in later recursive routines that
+ * traverse expression trees. Note that this is very unlikely to
+ * happen except with pathological queries; but we don't want someone
+ * to be able to crash the backend quite that easily...
+ */
+ if (++expr_depth_counter > max_expr_depth)
+ elog(ERROR, "Expression too complex: nesting depth exceeds max_expr_depth = %d",
+ max_expr_depth);
+
switch (nodeTag(expr))
{
case T_Attr:
@@ -532,6 +562,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
break;
}
+ expr_depth_counter--;
+
return result;
}
diff --git a/src/backend/parser/parser.c b/src/backend/parser/parser.c
index a4be685e20..488df8a8c9 100644
--- a/src/backend/parser/parser.c
+++ b/src/backend/parser/parser.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.43 2000/01/26 05:56:43 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.44 2000/03/17 05:29:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,6 +16,7 @@
#include "parser/analyze.h"
#include "parser/gramparse.h"
#include "parser/parser.h"
+#include "parser/parse_expr.h"
#if defined(FLEX_SCANNER)
extern void DeleteBuffer(void);
@@ -46,6 +47,8 @@ parser(char *str, Oid *typev, int nargs)
parsetree = NIL; /* in case parser forgets to set it */
parser_init(typev, nargs);
+ parse_expr_init();
+
yyresult = yyparse();
#if defined(FLEX_SCANNER)