mirror of
https://github.com/postgres/postgres.git
synced 2025-06-13 07:41:39 +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:
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.31 2000/02/27 21:07:03 tgl Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.32 2000/03/17 05:29:03 tgl Exp $
|
||||||
Postgres documentation
|
Postgres documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -770,6 +770,30 @@ SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>MAX_EXPR_DEPTH</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
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.)
|
||||||
|
|
||||||
|
<variablelist>
|
||||||
|
<varlistentry>
|
||||||
|
<term><replaceable class="parameter">integer</replaceable></term>
|
||||||
|
<term>ON</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Maximum depth.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
</variablelist>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 "miscadmin.h"
|
||||||
#include "optimizer/cost.h"
|
#include "optimizer/cost.h"
|
||||||
#include "optimizer/paths.h"
|
#include "optimizer/paths.h"
|
||||||
|
#include "parser/parse_expr.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/tqual.h"
|
#include "utils/tqual.h"
|
||||||
#include "utils/trace.h"
|
#include "utils/trace.h"
|
||||||
@ -86,6 +87,9 @@ static bool parse_geqo(char *);
|
|||||||
static bool show_ksqo(void);
|
static bool show_ksqo(void);
|
||||||
static bool reset_ksqo(void);
|
static bool reset_ksqo(void);
|
||||||
static bool parse_ksqo(char *);
|
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 show_XactIsoLevel(void);
|
||||||
static bool reset_XactIsoLevel(void);
|
static bool reset_XactIsoLevel(void);
|
||||||
static bool parse_XactIsoLevel(char *);
|
static bool parse_XactIsoLevel(char *);
|
||||||
@ -935,6 +939,44 @@ reset_ksqo()
|
|||||||
return TRUE;
|
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 */
|
/* SET TRANSACTION */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -1103,6 +1145,10 @@ static struct VariableParsers
|
|||||||
{
|
{
|
||||||
"ksqo", parse_ksqo, show_ksqo, reset_ksqo
|
"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
|
"XactIsoLevel", parse_XactIsoLevel, show_XactIsoLevel, reset_XactIsoLevel
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/builtins.h"
|
||||||
#include "utils/syscache.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_constant(Value *expr, TypeName *typename);
|
||||||
static Node *parser_typecast_expression(ParseState *pstate,
|
static Node *parser_typecast_expression(ParseState *pstate,
|
||||||
Node *expr, TypeName *typename);
|
Node *expr, TypeName *typename);
|
||||||
@ -40,6 +45,20 @@ static Node *transformIdent(ParseState *pstate, Ident *ident, int precedence);
|
|||||||
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
static Node *transformIndirection(ParseState *pstate, Node *basenode,
|
||||||
List *indirection);
|
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 -
|
* transformExpr -
|
||||||
* analyze and transform expressions. Type checking and type casting is
|
* analyze and transform expressions. Type checking and type casting is
|
||||||
@ -55,6 +74,17 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
|||||||
if (expr == NULL)
|
if (expr == NULL)
|
||||||
return 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))
|
switch (nodeTag(expr))
|
||||||
{
|
{
|
||||||
case T_Attr:
|
case T_Attr:
|
||||||
@ -532,6 +562,8 @@ transformExpr(ParseState *pstate, Node *expr, int precedence)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expr_depth_counter--;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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/analyze.h"
|
||||||
#include "parser/gramparse.h"
|
#include "parser/gramparse.h"
|
||||||
#include "parser/parser.h"
|
#include "parser/parser.h"
|
||||||
|
#include "parser/parse_expr.h"
|
||||||
|
|
||||||
#if defined(FLEX_SCANNER)
|
#if defined(FLEX_SCANNER)
|
||||||
extern void DeleteBuffer(void);
|
extern void DeleteBuffer(void);
|
||||||
@ -46,6 +47,8 @@ parser(char *str, Oid *typev, int nargs)
|
|||||||
parsetree = NIL; /* in case parser forgets to set it */
|
parsetree = NIL; /* in case parser forgets to set it */
|
||||||
|
|
||||||
parser_init(typev, nargs);
|
parser_init(typev, nargs);
|
||||||
|
parse_expr_init();
|
||||||
|
|
||||||
yyresult = yyparse();
|
yyresult = yyparse();
|
||||||
|
|
||||||
#if defined(FLEX_SCANNER)
|
#if defined(FLEX_SCANNER)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Copyright 2000 by PostgreSQL Global Development Group
|
* 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",
|
"client_encoding",
|
||||||
"server_encoding",
|
"server_encoding",
|
||||||
"KSQO",
|
"KSQO",
|
||||||
|
"max_expr_depth",
|
||||||
"XactIsoLevel",
|
"XactIsoLevel",
|
||||||
"PG_Options",
|
"PG_Options",
|
||||||
NULL
|
NULL
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* PostgreSQL configuration-settings file.
|
||||||
/* 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
|
* config.h.in is processed by configure to produce config.h.
|
||||||
* eventual use of autoconf to build the server
|
*
|
||||||
|
* 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
|
#ifndef CONFIG_H
|
||||||
@ -11,7 +17,7 @@
|
|||||||
/*
|
/*
|
||||||
* Default runtime limit on number of backend server processes per postmaster;
|
* Default runtime limit on number of backend server processes per postmaster;
|
||||||
* this is just the default setting for the postmaster's -N switch.
|
* 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
|
#undef DEF_MAXBACKENDS
|
||||||
|
|
||||||
@ -70,17 +76,11 @@
|
|||||||
/*
|
/*
|
||||||
* DEF_PGPORT is the TCP port number on which the Postmaster listens by
|
* DEF_PGPORT is the TCP port number on which the Postmaster listens by
|
||||||
* default. This can be overriden by command options, environment variables,
|
* 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
|
#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
|
* As soon as the backend blocks on a lock, it waits this number of seconds
|
||||||
* before checking for a deadlock.
|
* before checking for a deadlock.
|
||||||
@ -89,12 +89,6 @@
|
|||||||
*/
|
*/
|
||||||
#define DEADLOCK_CHECK_TIMER 1
|
#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
|
* Maximum number of columns in an index and maximum number of arguments
|
||||||
* to a function. They must be the same value.
|
* to a function. They must be the same value.
|
||||||
@ -121,16 +115,6 @@
|
|||||||
*/
|
*/
|
||||||
/* #define UNSAFE_FLOATS */
|
/* #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
|
* Define this to make libpgtcl's "pg_result -assign" command process C-style
|
||||||
* backslash sequences in returned tuple data and convert Postgres array
|
* backslash sequences in returned tuple data and convert Postgres array
|
||||||
@ -188,7 +172,7 @@
|
|||||||
#define FASTBUILD /* access/nbtree/nbtsort.c */
|
#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.
|
* transaction block after this query is done.
|
||||||
*/
|
*/
|
||||||
#define TBL_FREE_CMD_MEMORY
|
#define TBL_FREE_CMD_MEMORY
|
||||||
@ -232,9 +216,22 @@
|
|||||||
*/
|
*/
|
||||||
#define MAXPGPATH 1024
|
#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.
|
||||||
*------------------------------------------------------------------------
|
*------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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_COLUMN_FIRST 1
|
||||||
#define EXPR_RELATION_FIRST 2
|
#define EXPR_RELATION_FIRST 2
|
||||||
|
|
||||||
|
extern int max_expr_depth;
|
||||||
|
|
||||||
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
|
extern Node *transformExpr(ParseState *pstate, Node *expr, int precedence);
|
||||||
extern Oid exprType(Node *expr);
|
extern Oid exprType(Node *expr);
|
||||||
extern int32 exprTypmod(Node *expr);
|
extern int32 exprTypmod(Node *expr);
|
||||||
extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod);
|
extern bool exprIsLengthCoercion(Node *expr, int32 *coercedTypmod);
|
||||||
|
extern void parse_expr_init(void);
|
||||||
|
|
||||||
#endif /* PARSE_EXPR_H */
|
#endif /* PARSE_EXPR_H */
|
||||||
|
Reference in New Issue
Block a user