diff options
Diffstat (limited to 'src/backend')
| -rw-r--r-- | src/backend/commands/variable.c | 48 | ||||
| -rw-r--r-- | src/backend/parser/parse_expr.c | 34 | ||||
| -rw-r--r-- | src/backend/parser/parser.c | 5 |
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) |
