v1-0001-Fix-arrays-comparison-in-CompareOpclassOptions.patch

application/octet-stream

Filename: v1-0001-Fix-arrays-comparison-in-CompareOpclassOptions.patch
Type: application/octet-stream
Part: 0
Message: Re: BUG #18692: Segmentation fault when extending a varchar column with a gist index with custom signal length

Patch

Format: format-patch
Series: patch v1-0001
Subject: Fix arrays comparison in CompareOpclassOptions()
File+
contrib/pg_trgm/expected/pg_trgm.out 3 0
contrib/pg_trgm/sql/pg_trgm.sql 4 0
src/backend/commands/indexcmds.c 14 10
From 25680283fe0c9ef21a640763b712f277a6ca0188 Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Fri, 8 Nov 2024 00:23:00 +0200
Subject: [PATCH v1] Fix arrays comparison in CompareOpclassOptions()

The current code calls array_eq() without providing FmgrInfo.  This commit
makes this check stricter and simpler using datumIsEqual(), which should be
fine the the current usage scenario.

Reported-by: Nicolas Maus
Discussion: https://postgr.es/m/18692-72ea398df3ec6712%40postgresql.org
---
 contrib/pg_trgm/expected/pg_trgm.out |  3 +++
 contrib/pg_trgm/sql/pg_trgm.sql      |  4 ++++
 src/backend/commands/indexcmds.c     | 24 ++++++++++++++----------
 3 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out
index ce4bf1d4e51..0b70d9de256 100644
--- a/contrib/pg_trgm/expected/pg_trgm.out
+++ b/contrib/pg_trgm/expected/pg_trgm.out
@@ -2372,6 +2372,9 @@ ERROR:  value 2025 out of bounds for option "siglen"
 DETAIL:  Valid values are between "1" and "2024".
 create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024));
 set enable_seqscan=off;
+-- check index compatibility handling when opclass option is specified
+alter table test_trgm alter column t type varchar(768);
+alter table test_trgm alter column t type text;
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
       t      |   sml    
 -------------+----------
diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql
index 6a9da24d5a7..340c9891899 100644
--- a/contrib/pg_trgm/sql/pg_trgm.sql
+++ b/contrib/pg_trgm/sql/pg_trgm.sql
@@ -52,6 +52,10 @@ create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2025));
 create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024));
 set enable_seqscan=off;
 
+-- check index compatibility handling when opclass option is specified
+alter table test_trgm alter column t type varchar(768);
+alter table test_trgm alter column t type text;
+
 select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t;
 select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t;
 select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t;
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 2f652463e3c..01fc89a638c 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -60,6 +60,7 @@
 #include "storage/procarray.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/datum.h"
 #include "utils/fmgroids.h"
 #include "utils/guc.h"
 #include "utils/injection_point.h"
@@ -371,19 +372,22 @@ CompareOpclassOptions(const Datum *opts1, const Datum *opts2, int natts)
 		Datum		opt1 = opts1 ? opts1[i] : (Datum) 0;
 		Datum		opt2 = opts2 ? opts2[i] : (Datum) 0;
 
-		if (opt1 == (Datum) 0)
+		if (opt1 && opt2)
 		{
-			if (opt2 == (Datum) 0)
-				continue;
-			else
+			/*
+			 * Compare non-NULL text[] datums.  We are strict and require
+			 * arrays to be binary same.  This is fine with the current usage
+			 * scenario involving get_reloptions(), then re-parsing and
+			 * transformRelOptions().
+			 */
+			if (!datumIsEqual(opts1[i], opts2[i], false, -1))
+				return false;
+		}
+		else
+		{
+			if (opt1 != opt2)
 				return false;
 		}
-		else if (opt2 == (Datum) 0)
-			return false;
-
-		/* Compare non-NULL text[] datums. */
-		if (!DatumGetBool(DirectFunctionCall2(array_eq, opt1, opt2)))
-			return false;
 	}
 
 	return true;
-- 
2.39.5 (Apple Git-154)