0001-Re-add-regression-tests-for-ltree-and-intarray.patch

text/plain

Filename: 0001-Re-add-regression-tests-for-ltree-and-intarray.patch
Type: text/plain
Part: 0
Message: Re-add recently-removed tests for ltree and intarray
From d11a1dc0e8dc8d4838ca81fe8d4aa935cc1ed2df Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Thu, 14 May 2026 13:40:00 +0900
Subject: [PATCH] Re-add regression tests for ltree and intarray

These tests have been removed by 906ea101d0d5, due to some of them being
unstable in the buildfarm with low max_stack_depth values.  These tests
are reworked to be more portable.

The tests to cover the findoprnd() overflows use a balanced tree to
avoid using too much stack, per a suggestion by Tom Lane.

Backpatch-through: 14
---
 contrib/intarray/expected/_int.out | 15 +++++++++++++++
 contrib/intarray/sql/_int.sql      | 13 +++++++++++++
 contrib/ltree/expected/ltree.out   | 24 ++++++++++++++++++++++++
 contrib/ltree/sql/ltree.sql        | 20 ++++++++++++++++++++
 4 files changed, 72 insertions(+)

diff --git a/contrib/intarray/expected/_int.out b/contrib/intarray/expected/_int.out
index d0e68d0447fb..fb4086a95caf 100644
--- a/contrib/intarray/expected/_int.out
+++ b/contrib/intarray/expected/_int.out
@@ -398,6 +398,21 @@ SELECT '1&(2&(4&(5|!6)))'::query_int;
  1 & 2 & 4 & ( 5 | !6 )
 (1 row)
 
+-- Test for overflow of the int16 "left" field in findoprnd().
+-- This query uses a balanced binary tree to avoid using too much stack.
+DO $$
+DECLARE
+  e text := '1';
+BEGIN
+  FOR i IN 1..15 LOOP
+    e := '(' || e || '&' || e || ')';
+  END LOOP;
+  PERFORM ('0|' || e)::query_int;
+END;
+$$;
+ERROR:  query_int expression is too complex
+CONTEXT:  SQL statement "SELECT ('0|' || e)::query_int"
+PL/pgSQL function inline_code_block line 8 at PERFORM
 -- test non-error-throwing input
 SELECT str as "query_int",
        pg_input_is_valid(str,'query_int') as ok,
diff --git a/contrib/intarray/sql/_int.sql b/contrib/intarray/sql/_int.sql
index 5668ab407045..0d30914725e1 100644
--- a/contrib/intarray/sql/_int.sql
+++ b/contrib/intarray/sql/_int.sql
@@ -75,6 +75,19 @@ SELECT '1&2&4&5&6'::query_int;
 SELECT '1&(2&(4&(5|6)))'::query_int;
 SELECT '1&(2&(4&(5|!6)))'::query_int;
 
+-- Test for overflow of the int16 "left" field in findoprnd().
+-- This query uses a balanced binary tree to avoid using too much stack.
+DO $$
+DECLARE
+  e text := '1';
+BEGIN
+  FOR i IN 1..15 LOOP
+    e := '(' || e || '&' || e || ')';
+  END LOOP;
+  PERFORM ('0|' || e)::query_int;
+END;
+$$;
+
 -- test non-error-throwing input
 
 SELECT str as "query_int",
diff --git a/contrib/ltree/expected/ltree.out b/contrib/ltree/expected/ltree.out
index d2a566284755..15b9131a7506 100644
--- a/contrib/ltree/expected/ltree.out
+++ b/contrib/ltree/expected/ltree.out
@@ -1283,6 +1283,21 @@ SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_rw%*'::ltxtquery;
  f
 (1 row)
 
+-- Test for overflow of the int16 "left" field in findoprnd().
+-- This query uses a balanced binary tree to avoid using too much stack.
+DO $$
+DECLARE
+  e text := 'a';
+BEGIN
+  FOR i IN 1..14 LOOP
+    e := '(' || e || '&' || e || ')';
+  END LOOP;
+  PERFORM ('b|' || e)::ltxtquery;
+END;
+$$;
+ERROR:  ltxtquery is too large
+CONTEXT:  SQL statement "SELECT ('b|' || e)::ltxtquery"
+PL/pgSQL function inline_code_block line 8 at PERFORM
 --arrays
 SELECT '{1.2.3}'::ltree[] @> '1.2.3.4';
  ?column? 
@@ -8202,3 +8217,12 @@ FROM (VALUES ('.2.3', 'ltree'),
  !tree & aWdf@* | ltxtquery | t  |                |                                    |                          | 
 (8 rows)
 
+-- Test for overflow of lquery_level.totallen.
+SELECT (repeat('x', 255) || repeat('|' || repeat('x', 255), 256))::lquery;
+ERROR:  lquery level is too large
+DETAIL:  Total size of level exceeds the maximum allowed (65535 bytes).
+--- Test for overflow of lquery_level.numvar, with a set of single-char
+--- variants in one level.
+SELECT (repeat('a|', 65535) || 'a')::lquery;
+ERROR:  lquery level has too many variants
+DETAIL:  Number of variants exceeds the maximum allowed (65535).
diff --git a/contrib/ltree/sql/ltree.sql b/contrib/ltree/sql/ltree.sql
index 77e6958c62a7..d0fade9d17d8 100644
--- a/contrib/ltree/sql/ltree.sql
+++ b/contrib/ltree/sql/ltree.sql
@@ -253,6 +253,19 @@ SELECT 'tree.awdfg'::ltree @ 'tree & aWdfg@'::ltxtquery;
 SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_qw%*'::ltxtquery;
 SELECT 'tree.awdfg_qwerty'::ltree @ 'tree & aw_rw%*'::ltxtquery;
 
+-- Test for overflow of the int16 "left" field in findoprnd().
+-- This query uses a balanced binary tree to avoid using too much stack.
+DO $$
+DECLARE
+  e text := 'a';
+BEGIN
+  FOR i IN 1..14 LOOP
+    e := '(' || e || '&' || e || ')';
+  END LOOP;
+  PERFORM ('b|' || e)::ltxtquery;
+END;
+$$;
+
 --arrays
 
 SELECT '{1.2.3}'::ltree[] @> '1.2.3.4';
@@ -457,3 +470,10 @@ FROM (VALUES ('.2.3', 'ltree'),
              ('!tree & aWdf@*','ltxtquery'))
       AS a(str,typ),
      LATERAL pg_input_error_info(a.str, a.typ) as errinfo;
+
+-- Test for overflow of lquery_level.totallen.
+SELECT (repeat('x', 255) || repeat('|' || repeat('x', 255), 256))::lquery;
+
+--- Test for overflow of lquery_level.numvar, with a set of single-char
+--- variants in one level.
+SELECT (repeat('a|', 65535) || 'a')::lquery;
-- 
2.54.0