public inbox for [email protected]
help / color / mirror / Atom feedFrom: Ashutosh Bapat <[email protected]>
To: SATYANARAYANA NARLAPURAM <[email protected]>
Cc: PostgreSQL Hackers <[email protected]>
Cc: Peter Eisentraut <[email protected]>
Subject: Re: Bug: Missing check_stack_depth() in GRAPH_TABLE rewriter
Date: Wed, 15 Apr 2026 20:37:40 +0530
Message-ID: <CAExHW5sEQOK3F+pkZcFy=FX-dOhdittBS6A7Hf88HT841bunLg@mail.gmail.com> (raw)
In-Reply-To: <CAHg+QDfgK0xddH8f3eAb+UVn7sBDOnv8RvM6OkP4HtHAt6aD7w@mail.gmail.com>
References: <CAHg+QDfgK0xddH8f3eAb+UVn7sBDOnv8RvM6OkP4HtHAt6aD7w@mail.gmail.com>
On Sat, Apr 11, 2026 at 9:28 AM SATYANARAYANA NARLAPURAM
<[email protected]> wrote:
>
> Hi Hackers,
>
> Two recursive functions, generate_setop_from_pathqueries() and
> generate_queries_for_path_pattern_recurse() in GRAPH_TABLE rewriter are missing check_stack_depth() calls. Consider a property graph with 400 edge tables with a 2-hop pattern produce 160,000 path queries and therefore 160,000 recursion frames in
> generate_setop_from_pathqueries(). This can easily exceed the OS stack limit for some systems and crashes the backend.
>
> I am proposing a stop gap fix of checking stack depth by calling check_stack_depth for now but in future we may want to reduce the recursion depth (for example use a balanced tree to reduce depth from O(N) to O(log N).
>
> Attached a patch for adding the check_stack_depth() check.
>
> Repro:
>
> CREATE TABLE sv (id int PRIMARY KEY);
> INSERT INTO sv VALUES (1);
>
> DO $$
> BEGIN
> FOR i IN 1..400 LOOP
> EXECUTE format(
> 'CREATE TABLE se_%s (id int PRIMARY KEY, src int, dst int)', i);
> END LOOP;
> END$$;
>
> DO $$
> DECLARE
> sql text;
> edges text := '';
> BEGIN
> FOR i IN 1..400 LOOP
> IF i > 1 THEN edges := edges || ', '; END IF;
> edges := edges || format(
> 'se_%s KEY (id) SOURCE KEY (src) REFERENCES sv (id) '
> 'DESTINATION KEY (dst) REFERENCES sv (id)', i);
> END LOOP;
> EXECUTE 'CREATE PROPERTY GRAPH g VERTEX TABLES (sv KEY (id)) '
> || 'EDGE TABLES (' || edges || ')';
> END$$;
>
> SELECT * FROM GRAPH_TABLE(g
> MATCH (a)-[e1]->(b)-[e2]->(c)
> COLUMNS(a.id AS a_id))
> LIMIT 1;
>
Thanks for the report. I could reproduce the segfault on my laptop.
The attached patch fixes it and gives ERROR: stack depth limit
exceeded.
generate_queries_for_path_pattern_recurse() - has to work in a linear
fashion since the elements need to be processed in an order. Each
permutation of elements produces one query. These queries can be
arranged in a balanced tree as you suggest OR when constructing the
setop tree we could generate it in divide-and-conquer manner. However,
the tree will be flattened in the planner anyway (See
flatten_simple_union_all() and pull_up_simple_union_all()). Thus the
final planning will require a deeper stack anyway. The code complexity
doesn't seem to be worth it.
I also looked at a few commits that add check_stack_depth() to see if
we add tests for these scenarios. But I didn't find any. So no tests
added with this commit.
--
Best Wishes,
Ashutosh Bapat
Attachments:
[text/x-patch] v20260415-0001-Check-for-stack-overflow-when-rewriting-gr.patch (2.1K, 2-v20260415-0001-Check-for-stack-overflow-when-rewriting-gr.patch)
download | inline diff:
From 71a851e9d74e1c3d74428700eca1f11437600bcd Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <[email protected]>
Date: Wed, 15 Apr 2026 17:38:25 +0530
Subject: [PATCH v20260415 2/3] Check for stack overflow when rewriting graph
queries.
generate_queries_for_path_pattern_recurse() and
generate_setop_from_pathqueries() are recursive functions. For a property graph
with hundreds of tables, a graph pattern with a handful element patterns can
cause stack overflow. Fix it by calling check_stack_depth() at the beginning of
these functions.
Reported-by: Satyanarayana Narlapuram <[email protected]>
Author: Satyanarayana Narlapuram <[email protected]>
Reviewed-by: Ashutosh Bapat <[email protected]>
Discussion: https://www.postgresql.org/message-id/CAHg+QDfgK0xddH8f3eAb+UVn7sBDOnv8RvM6OkP4HtHAt6aD7w@mail.gmail.com
---
src/backend/rewrite/rewriteGraphTable.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c
index 2c3199d3230..429ef1cf1f4 100644
--- a/src/backend/rewrite/rewriteGraphTable.c
+++ b/src/backend/rewrite/rewriteGraphTable.c
@@ -17,6 +17,7 @@
#include "access/sysattr.h"
#include "access/table.h"
#include "access/htup_details.h"
+#include "miscadmin.h"
#include "catalog/pg_operator.h"
#include "catalog/pg_propgraph_element.h"
#include "catalog/pg_propgraph_element_label.h"
@@ -361,6 +362,9 @@ generate_queries_for_path_pattern_recurse(RangeTblEntry *rte, List *pathqueries,
{
List *path_elems = list_nth_node(List, path_elem_lists, elempos);
+ /* Guard against stack overflow due to complex path patterns. */
+ check_stack_depth();
+
foreach_ptr(struct path_element, pe, path_elems)
{
/* Update current path being built with current element. */
@@ -698,6 +702,9 @@ generate_setop_from_pathqueries(List *pathqueries, List **rtable, List **targetl
List *rtargetlist;
ParseNamespaceItem *pni;
+ /* Guard against stack overflow due to many path queries. */
+ check_stack_depth();
+
/* Recursion termination condition. */
if (list_length(pathqueries) == 0)
{
--
2.34.1
view thread (4+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected]
Subject: Re: Bug: Missing check_stack_depth() in GRAPH_TABLE rewriter
In-Reply-To: <CAExHW5sEQOK3F+pkZcFy=FX-dOhdittBS6A7Hf88HT841bunLg@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox