aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-10-02 14:51:58 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-10-02 14:51:58 -0400
commitb63fc28776c5d2efdb4de326ad0f0b5b88f82220 (patch)
tree74bf395229d6c60aa24463714340ce1e41fdfc14 /src/backend/tcop/postgres.c
parentf2c4ffc3307cab6619a28e77da9211416c8b1d83 (diff)
downloadpostgresql-b63fc28776c5d2efdb4de326ad0f0b5b88f82220.tar.gz
postgresql-b63fc28776c5d2efdb4de326ad0f0b5b88f82220.zip
Add recursion depth protections to regular expression matching.
Some of the functions in regex compilation and execution recurse, and therefore could in principle be driven to stack overflow. The Tcl crew has seen this happen in practice in duptraverse(), though their fix was to put in a hard-wired limit on the number of recursive levels, which is not too appetizing --- fortunately, we have enough infrastructure to check the actually available stack. Greg Stark has also seen it in other places while fuzz testing on a machine with limited stack space. Let's put guards in to prevent crashes in all these places. Since the regex code would leak memory if we simply threw elog(ERROR), we have to introduce an API that checks for stack depth without throwing such an error. Fortunately that's not difficult.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c39
1 files changed, 22 insertions, 17 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index d1f43c5c8a2..aee13aec757 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3081,16 +3081,33 @@ restore_stack_base(pg_stack_base_t base)
}
/*
- * check_stack_depth: check for excessively deep recursion
+ * check_stack_depth/stack_is_too_deep: check for excessively deep recursion
*
* This should be called someplace in any recursive routine that might possibly
* recurse deep enough to overflow the stack. Most Unixen treat stack
* overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
* before hitting the hardware limit.
+ *
+ * check_stack_depth() just throws an error summarily. stack_is_too_deep()
+ * can be used by code that wants to handle the error condition itself.
*/
void
check_stack_depth(void)
{
+ if (stack_is_too_deep())
+ {
+ ereport(ERROR,
+ (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
+ errmsg("stack depth limit exceeded"),
+ errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
+ "after ensuring the platform's stack depth limit is adequate.",
+ max_stack_depth)));
+ }
+}
+
+bool
+stack_is_too_deep(void)
+{
char stack_top_loc;
long stack_depth;
@@ -3115,14 +3132,7 @@ check_stack_depth(void)
*/
if (stack_depth > max_stack_depth_bytes &&
stack_base_ptr != NULL)
- {
- ereport(ERROR,
- (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
- errmsg("stack depth limit exceeded"),
- errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
- "after ensuring the platform's stack depth limit is adequate.",
- max_stack_depth)));
- }
+ return true;
/*
* On IA64 there is a separate "register" stack that requires its own
@@ -3137,15 +3147,10 @@ check_stack_depth(void)
if (stack_depth > max_stack_depth_bytes &&
register_stack_base_ptr != NULL)
- {
- ereport(ERROR,
- (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
- errmsg("stack depth limit exceeded"),
- errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
- "after ensuring the platform's stack depth limit is adequate.",
- max_stack_depth)));
- }
+ return true;
#endif /* IA64 */
+
+ return false;
}
/* GUC check hook for max_stack_depth */