1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

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.
This commit is contained in:
Tom Lane
2000-03-17 05:29:07 +00:00
parent 341b328b18
commit 0e314d747e
7 changed files with 143 additions and 37 deletions

View File

@ -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
@ -1103,6 +1145,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
},

View File

@ -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;
}

View File

@ -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)

View File

@ -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

View File

@ -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,17 +76,11 @@
/*
* 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.
@ -89,12 +89,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.
@ -121,16 +115,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
@ -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
@ -232,9 +216,22 @@
*/
#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.
*------------------------------------------------------------------------
*/

View File

@ -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 */