Skip to content

Commit

Permalink
Add some recursion and looping defenses in prepjointree.c.
Browse files Browse the repository at this point in the history
Andrey Lepikhov demonstrated a case where we spend an unreasonable
amount of time in pull_up_subqueries().  Not only is that recursing
with no explicit check for stack overrun, but the code seems not
interruptable by control-C.  Let's stick a CHECK_FOR_INTERRUPTS
there, along with sprinkling some stack depth checks.

An actual fix for the excessive time consumption seems a bit
risky to back-patch; but this isn't, so let's do so.

Discussion: https://postgr.es/m/703c09a2-08f3-d2ec-b33d-dbecd62428b8@postgrespro.ru
  • Loading branch information
tglsfdc committed Dec 22, 2022
1 parent 73bb72f commit 5beb788
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/backend/optimizer/prep/prepjointree.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/multibitmapset.h"
#include "nodes/nodeFuncs.h"
Expand Down Expand Up @@ -308,6 +309,9 @@ static Node *
pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode,
Relids *relids)
{
/* Since this function recurses, it could be driven to stack overflow. */
check_stack_depth();

if (jtnode == NULL)
{
*relids = NULL;
Expand Down Expand Up @@ -805,6 +809,11 @@ pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode,
JoinExpr *lowest_nulling_outer_join,
AppendRelInfo *containing_appendrel)
{
/* Since this function recurses, it could be driven to stack overflow. */
check_stack_depth();
/* Also, since it's a bit expensive, let's check for query cancel. */
CHECK_FOR_INTERRUPTS();

Assert(jtnode != NULL);
if (IsA(jtnode, RangeTblRef))
{
Expand Down Expand Up @@ -1937,6 +1946,9 @@ is_simple_union_all(Query *subquery)
static bool
is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
{
/* Since this function recurses, it could be driven to stack overflow. */
check_stack_depth();

if (IsA(setOp, RangeTblRef))
{
RangeTblRef *rtr = (RangeTblRef *) setOp;
Expand Down

0 comments on commit 5beb788

Please sign in to comment.