pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Alexander Lakhin <exclusion@gmail.com>
To: pgsql-bugs@lists.postgresql.org
Subject: Re: BUG #17950: Incorrect memory access in gtsvector_picksplit()
Date: Sun, 13 Aug 2023 16:00:01 +0300
Message-ID: <e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com> (raw)
In-Reply-To: <da453149-fa9e-67fc-fbce-80cca399bce5@gmail.com>
References: <17950-6c80a8d2b94ec695@postgresql.org>
	<da453149-fa9e-67fc-fbce-80cca399bce5@gmail.com>

17.06.2023 17:00, Alexander Lakhin wrote:
> 29.05.2023 23:00, PG Bug reporting form wrote:
>> The following bug has been logged on the website:
>>
>> Bug reference:      17950
>
> I managed to reduce the reproducer to the following:
> CREATE TABLE tst(t tsvector);
> INSERT INTO tst SELECT array_to_string(array(SELECT 'a' || x::text FROM generate_series(1, 125) x), ' ')::tsvector 
> FROM generate_series(1, 3000);
> INSERT INTO tst SELECT '' FROM generate_series(1, 100);
> CREATE INDEX gistidx ON tst USING gist (t tsvector_ops(siglen=1));
>
>
> A trivial fix for the issue is attached.
>

I can also propose a regression test addition that demonstrates the valgrind
complaint and also the output of gtsvectorout() for the case ISALLTRUE and
the opposite.

This addition increases the duration of `make check -C contrib/pageinspect`
under valgrind by 7-8 seconds for me:
ok 5         - gist                                     2496 ms
->
ok 5         - gist                                     9890 ms

In absence of any objections or other propositions, I'm inclined to register
this bugfix on the commitfest.

Best regards,
Alexander

Attachments:

  [text/x-patch] v1-01-fix-gtsvector_picksplit.patch (718B, ../e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com/2-v1-01-fix-gtsvector_picksplit.patch)
  download | inline diff:
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index f0cd2866ff..12a4111e99 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -730,7 +730,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 				size_alpha = SIGLENBIT(siglen) -
 					sizebitvec((cache[j].allistrue) ?
 							   GETSIGN(datum_l) :
-							   GETSIGN(cache[j].sign),
+							   cache[j].sign,
 							   siglen);
 		}
 		else
@@ -744,7 +744,7 @@ gtsvector_picksplit(PG_FUNCTION_ARGS)
 				size_beta = SIGLENBIT(siglen) -
 					sizebitvec((cache[j].allistrue) ?
 							   GETSIGN(datum_r) :
-							   GETSIGN(cache[j].sign),
+							   cache[j].sign,
 							   siglen);
 		}
 		else


  [text/x-patch] v1-02-fix-gtsvectorout.patch (836B, ../e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com/3-v1-02-fix-gtsvectorout.patch)
  download | inline diff:
diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c
index 12a4111e99..2722c02457 100644
--- a/src/backend/utils/adt/tsgistidx.c
+++ b/src/backend/utils/adt/tsgistidx.c
@@ -115,10 +115,15 @@ gtsvectorout(PG_FUNCTION_ARGS)
 		sprintf(outbuf, ARROUTSTR, (int) ARRNELEM(key));
 	else
 	{
-		int			siglen = GETSIGLEN(key);
-		int			cnttrue = (ISALLTRUE(key)) ? SIGLENBIT(siglen) : sizebitvec(GETSIGN(key), siglen);
+		if (ISALLTRUE(key))
+			sprintf(outbuf, "all true bits");
+		else
+		{
+			int			siglen = GETSIGLEN(key);
+			int			cnttrue = (ISALLTRUE(key)) ? SIGLENBIT(siglen) : sizebitvec(GETSIGN(key), siglen);
 
-		sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT(siglen) - cnttrue);
+			sprintf(outbuf, SINGOUTSTR, cnttrue, (int) SIGLENBIT(siglen) - cnttrue);
+		}
 	}
 
 	PG_FREE_IF_COPY(key, 0);


  [text/x-patch] v1-03-test-for-tsgistidx.patch (2.4K, ../e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com/4-v1-03-test-for-tsgistidx.patch)
  download | inline diff:
diff --git a/contrib/pageinspect/expected/gist.out b/contrib/pageinspect/expected/gist.out
index d1adbab8ae..2f4d0b27b0 100644
--- a/contrib/pageinspect/expected/gist.out
+++ b/contrib/pageinspect/expected/gist.out
@@ -131,3 +131,29 @@ SELECT keys AS keys_leaf_1
 (1 row)
 
 DROP TABLE test_gist;
+-- Test for keys output by gtsvectorout() and also exercise
+-- a corner case of tsvector's picksplit.
+CREATE TABLE test_tsvector(t tsvector);
+INSERT INTO test_tsvector
+  SELECT array_to_string(array(SELECT 'a' || x::text FROM generate_series(1, 125) x), ' ')::tsvector
+  FROM generate_series(1, 3000);
+INSERT INTO test_tsvector SELECT '' FROM generate_series(1, 100);
+CREATE INDEX tsvector_gist_idx_1 ON test_tsvector USING gist (t tsvector_ops(siglen=1));
+CREATE INDEX tsvector_gist_idx_10 ON test_tsvector USING gist (t tsvector_ops(siglen=10));
+SELECT keys
+  FROM gist_page_items(get_raw_page('tsvector_gist_idx_1', 0), 'tsvector_gist_idx_1')
+  WHERE itemoffset = 1;
+         keys          
+-----------------------
+ (t)=("all true bits")
+(1 row)
+
+SELECT keys
+  FROM gist_page_items(get_raw_page('tsvector_gist_idx_10', 0), 'tsvector_gist_idx_10')
+  WHERE itemoffset = 1;
+                keys                 
+-------------------------------------
+ (t)=("62 true bits, 18 false bits")
+(1 row)
+
+DROP TABLE test_tsvector;
diff --git a/contrib/pageinspect/sql/gist.sql b/contrib/pageinspect/sql/gist.sql
index d263542ba1..3fe29317b9 100644
--- a/contrib/pageinspect/sql/gist.sql
+++ b/contrib/pageinspect/sql/gist.sql
@@ -67,3 +67,21 @@ SELECT keys AS keys_leaf_1
   WHERE itemoffset = 1;
 
 DROP TABLE test_gist;
+
+-- Test for keys output by gtsvectorout() and also exercise
+-- a corner case of tsvector's picksplit.
+CREATE TABLE test_tsvector(t tsvector);
+INSERT INTO test_tsvector
+  SELECT array_to_string(array(SELECT 'a' || x::text FROM generate_series(1, 125) x), ' ')::tsvector
+  FROM generate_series(1, 3000);
+INSERT INTO test_tsvector SELECT '' FROM generate_series(1, 100);
+CREATE INDEX tsvector_gist_idx_1 ON test_tsvector USING gist (t tsvector_ops(siglen=1));
+CREATE INDEX tsvector_gist_idx_10 ON test_tsvector USING gist (t tsvector_ops(siglen=10));
+
+SELECT keys
+  FROM gist_page_items(get_raw_page('tsvector_gist_idx_1', 0), 'tsvector_gist_idx_1')
+  WHERE itemoffset = 1;
+SELECT keys
+  FROM gist_page_items(get_raw_page('tsvector_gist_idx_10', 0), 'tsvector_gist_idx_10')
+  WHERE itemoffset = 1;
+DROP TABLE test_tsvector;


view thread (8+ messages)  latest in thread

Message-ID: <e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com>
Permalink:  ../e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com/
Also on:    postgresql.org/message-id/e2f36991-0519-bfcf-1da9-c31ca645b4ec@gmail.com

 ·  · 

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: pgsql-bugs@postgresql.org
  Cc: exclusion@gmail.com, pgsql-bugs@lists.postgresql.org
  Subject: Re: BUG #17950: Incorrect memory access in gtsvector_picksplit()
  In-Reply-To: <e2f36991-0519-bfcf-1da9-c31ca645b4ec@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 DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox