From: Tom Lane Date: Fri, 17 Mar 2000 05:29:07 +0000 (+0000) Subject: Add safety check on expression nesting depth. Default value is set by X-Git-Tag: REL9_0_0~23733 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=0e314d747e2803a9bea7ee69ab0c7df881277eba;p=pg-rex%2Fsyncrep.git Add safety check on expression nesting depth. Default value is set by a config.h #define, and the runtime value can be controlled via SET. --- diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml index 87d4d6f09e..cd6265eed6 100644 --- a/doc/src/sgml/ref/set.sgml +++ b/doc/src/sgml/ref/set.sgml @@ -1,5 +1,5 @@ @@ -770,6 +770,30 @@ SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } + + MAX_EXPR_DEPTH + + + Sets the maximum expression nesting depth that the parser will + accept. The default value is high enough for any normal query, + but you can raise it if you need to. (But if you raise it too high, + you run the risk of backend crashes due to stack overflow.) + + + + integer + ON + + + Maximum depth. + + + + + + + + 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) diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 54561cb377..5aec29dc89 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright 2000 by PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.15 2000/03/05 13:30:19 petere Exp $ + * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.16 2000/03/17 05:29:06 tgl Exp $ */ /*----------- @@ -195,6 +195,7 @@ char ** psql_completion(char *text, int start, int end) "client_encoding", "server_encoding", "KSQO", + "max_expr_depth", "XactIsoLevel", "PG_Options", NULL diff --git a/src/include/config.h.in b/src/include/config.h.in index fb472061f5..b7a95be0ed 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -1,8 +1,14 @@ - - -/* the purpose of this file is to reduce the use of #ifdef's through - * the code base by those porting the software, and to facilitate the - * eventual use of autoconf to build the server +/* + * PostgreSQL configuration-settings file. + * + * config.h.in is processed by configure to produce config.h. + * + * If you want to modify any of the tweakable settings in the first part + * of this file, you can do it in config.h.in before running configure, + * or in config.h afterwards. Of course, if you edit config.h, then your + * changes will be overwritten the next time you run configure. + * + * $Id: config.h.in,v 1.110 2000/03/17 05:29:06 tgl Exp $ */ #ifndef CONFIG_H @@ -11,7 +17,7 @@ /* * Default runtime limit on number of backend server processes per postmaster; * this is just the default setting for the postmaster's -N switch. - * (Actual value is set by configure script.) + * (Actual value is now set by configure script.) */ #undef DEF_MAXBACKENDS @@ -70,18 +76,12 @@ /* * DEF_PGPORT is the TCP port number on which the Postmaster listens by * default. This can be overriden by command options, environment variables, - * and the postconfig hook. (set by configure script) + * and the postconfig hook. (now set by configure script) */ #undef DEF_PGPORT /* - * If you do not plan to use Host based authentication, - * comment out the following line (set by build script) - */ -#undef HBA - -/* * As soon as the backend blocks on a lock, it waits this number of seconds * before checking for a deadlock. * We don't check for deadlocks just before sleeping because a deadlock is @@ -90,12 +90,6 @@ #define DEADLOCK_CHECK_TIMER 1 /* - * This flag enables the use of indexes in plans generated for function - * executions which normally are always executed with sequential scans. - */ -#define INDEXSCAN_PATCH - -/* * Maximum number of columns in an index and maximum number of arguments * to a function. They must be the same value. * @@ -122,16 +116,6 @@ /* #define UNSAFE_FLOATS */ /* - * There is a bug in the function executor. The backend crashes while trying to - * execute an sql function containing an utility command (create, notify, ...). - * The bug is part in the planner, which returns a number of plans different - * than the number of commands if there are utility commands in the query, and - * in part in the function executor which assumes that all commands are normal - * query commands and causes a SIGSEGV trying to execute commands without plan. - */ -#define FUNC_UTIL_PATCH - -/* * Define this to make libpgtcl's "pg_result -assign" command process C-style * backslash sequences in returned tuple data and convert Postgres array * attributes into Tcl lists. CAUTION: this conversion is *wrong* unless @@ -188,7 +172,7 @@ #define FASTBUILD /* access/nbtree/nbtsort.c */ /* - * TBL_FREE_CMD_MEMORY: free memory allocated for an user query inside + * TBL_FREE_CMD_MEMORY: free memory allocated for a user query inside * transaction block after this query is done. */ #define TBL_FREE_CMD_MEMORY @@ -233,8 +217,21 @@ #define MAXPGPATH 1024 /* + * DEFAULT_MAX_EXPR_DEPTH: default value of max_expr_depth SET variable. + */ +#define DEFAULT_MAX_EXPR_DEPTH 10000 + +/* + * Leftover cruft for enabling long-since-verified patches. + * You don't want to touch these. + */ +#define INDEXSCAN_PATCH +#define FUNC_UTIL_PATCH + + +/* *------------------------------------------------------------------------ - * The following is set using configure. + * Everything past here is set by the configure script. *------------------------------------------------------------------------ */ diff --git a/src/include/parser/parse_expr.h b/src/include/parser/parse_expr.h index 50d7b284bb..7c76001e4e 100644 --- a/src/include/parser/parse_expr.h +++ b/src/include/parser/parse_expr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: parse_expr.h,v 1.17 2000/02/26 21:11:09 tgl Exp $ + * $Id: parse_expr.h,v 1.18 2000/03/17 05:29:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,9 +20,12 @@ #define EXPR_COLUMN_FIRST 1 #define EXPR_RELATION_FIRST 2 +extern int max_expr_depth; + extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence); extern Oid exprType(Node *expr); extern int32 exprTypmod(Node *expr); extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod); +extern void parse_expr_init(void); #endif /* PARSE_EXPR_H */