pg.ddx.io pgsql-bugs@postgresql.org mailing list archive
help / color / mirror / Atom feedBUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
6+ messages / 3 participants
[nested] [flat]
* BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-01 05:53 PG Bug reporting form <noreply@postgresql.org>
0 siblings, 1 reply; 6+ messages in thread
From: PG Bug reporting form @ 2023-03-01 05:53 UTC (permalink / raw)
To: pgsql-bugs@lists.postgresql.org; +Cc: kyzevan23@mail.ru
The following bug has been logged on the website:
Bug reference: 17815
Logged by: Egor Chindyaskin
Email address: kyzevan23@mail.ru
PostgreSQL version: 15.2
Operating system: Ubuntu 22.04
Description:
When executing the following query:
CREATE EXTENSION pageinspect;
CREATE TABLE test_gist (p point, t text);
CREATE INDEX test_gist_idx ON test_gist USING gist (p);
CREATE INDEX test_gist_btree on test_gist(t);
SELECT gist_page_items(get_raw_page('test_gist_btree', 0),
'test_gist_idx');
DROP EXTENSION pageinspect;
I got server crash with the following backtrace:
Core was generated by `postgres: egorchin egorchin [local] SELECT
'.
Program terminated with signal SIGABRT, Aborted.
#0 __pthread_kill_implementation (no_tid=0, signo=6,
threadid=139699942591360) at ./nptl/pthread_kill.c:44
44 ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0 __pthread_kill_implementation (no_tid=0, signo=6,
threadid=139699942591360) at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=139699942591360) at
./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=139699942591360, signo=signo@entry=6) at
./nptl/pthread_kill.c:89
#3 0x00007f0e6d442476 in __GI_raise (sig=sig@entry=6) at
../sysdeps/posix/raise.c:26
#4 0x00007f0e6d4287f3 in __GI_abort () at ./stdlib/abort.c:79
#5 0x0000562438c9e2fc in ExceptionalCondition (conditionName=0x7f0e6d656c78
"ItemIdHasStorage(itemId)", fileName=0x7f0e6d656be0
"../../src/include/storage/bufpage.h", lineNumber=355)
at assert.c:66
#6 0x00007f0e6d64f2cd in PageGetItem (page=0x5624395f3148 "",
itemId=0x5624395f3164) at ../../src/include/storage/bufpage.h:355
#7 0x00007f0e6d65006e in gist_page_items (fcinfo=0x562439605db0) at
gistfuncs.c:254
#8 0x000056243881cab0 in ExecMakeFunctionResultSet (fcache=0x562439605150,
econtext=0x562439604750, argContext=0x5624395fd180, isNull=0x5624396050e0,
isDone=0x562439605138)
at execSRF.c:625
#9 0x000056243885e18f in ExecProjectSRF (node=0x562439604640,
continuing=false) at nodeProjectSet.c:175
#10 0x000056243885e048 in ExecProjectSet (pstate=0x562439604640) at
nodeProjectSet.c:105
#11 0x000056243881953a in ExecProcNodeFirst (node=0x562439604640) at
execProcnode.c:464
#12 0x000056243880c718 in ExecProcNode (node=0x562439604640) at
../../../src/include/executor/executor.h:262
#13 0x000056243880f54d in ExecutePlan (estate=0x562439604418,
planstate=0x562439604640, use_parallel_mode=false, operation=CMD_SELECT,
sendTuples=true, numberTuples=0,
direction=ForwardScanDirection, dest=0x56243960ad38, execute_once=true)
at execMain.c:1633
#14 0x000056243880ce00 in standard_ExecutorRun (queryDesc=0x56243960e768,
direction=ForwardScanDirection, count=0, execute_once=true) at
execMain.c:364
#15 0x000056243880cc09 in ExecutorRun (queryDesc=0x56243960e768,
direction=ForwardScanDirection, count=0, execute_once=true) at
execMain.c:308
#16 0x0000562438ac07cd in PortalRunSelect (portal=0x5624395843e8,
forward=true, count=0, dest=0x56243960ad38) at pquery.c:924
#17 0x0000562438ac03f5 in PortalRun (portal=0x5624395843e8,
count=9223372036854775807, isTopLevel=true, run_once=true,
dest=0x56243960ad38, altdest=0x56243960ad38, qc=0x7ffe83e284d0)
at pquery.c:768
#18 0x0000562438ab91de in exec_simple_query (query_string=0x56243950ae88
"SELECT gist_page_items(get_raw_page('test_gist_btree', 0),
'test_gist_idx');") at postgres.c:1240
#19 0x0000562438abe21a in PostgresMain (dbname=0x562439542368 "egorchin",
username=0x562439542348 "egorchin") at postgres.c:4572
#20 0x00005624389e1f40 in BackendRun (port=0x562439539b80) at
postmaster.c:4461
#21 0x00005624389e17cc in BackendStartup (port=0x562439539b80) at
postmaster.c:4189
#22 0x00005624389ddb11 in ServerLoop () at postmaster.c:1779
#23 0x00005624389dd3bb in PostmasterMain (argc=3, argv=0x5624395053b0) at
postmaster.c:1463
#24 0x00005624388974e1 in main (argc=3, argv=0x5624395053b0) at main.c:200
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-01 09:31 Dmitry Koval <d.koval@postgrespro.ru>
parent: PG Bug reporting form <noreply@postgresql.org>
0 siblings, 1 reply; 6+ messages in thread
From: Dmitry Koval @ 2023-03-01 09:31 UTC (permalink / raw)
To: pgsql-bugs@lists.postgresql.org
Hi,
Attached fix for "master" branch.
--
With best regards,
Dmitry Koval
Postgres Professional: http://postgrespro.com
diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index 100697814d..2b252f85bd 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -32,13 +32,14 @@ PG_FUNCTION_INFO_V1(gist_page_items_bytea);
#define IS_GIST(r) ((r)->rd_rel->relam == GIST_AM_OID)
+static Page verify_gist_page(bytea *raw_page);
+
Datum
gist_page_opaque_info(PG_FUNCTION_ARGS)
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
TupleDesc tupdesc;
Page page;
- GISTPageOpaque opaq;
HeapTuple resultTuple;
Datum values[4];
bool nulls[4];
@@ -51,35 +52,17 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
PG_RETURN_NULL();
- /* verify the special space has the expected size */
- if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected special size %d, got %d.",
- (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
- (int) PageGetSpecialSize(page))));
-
- opaq = GistPageGetOpaque(page);
- if (opaq->gist_page_id != GIST_PAGE_ID)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected %08x, got %08x.",
- GIST_PAGE_ID,
- opaq->gist_page_id)));
-
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
/* Convert the flags bitmask to an array of human-readable names */
- flagbits = opaq->flags;
+ flagbits = GistPageGetOpaque(page)->flags;
if (flagbits & F_LEAF)
flags[nflags++] = CStringGetTextDatum("leaf");
if (flagbits & F_DELETED)
@@ -101,7 +84,7 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
values[0] = LSNGetDatum(PageGetLSN(page));
values[1] = LSNGetDatum(GistPageGetNSN(page));
- values[2] = Int64GetDatum(opaq->rightlink);
+ values[2] = Int64GetDatum(GistPageGetOpaque(page)->rightlink);
values[3] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID));
/* Build and return the result tuple. */
@@ -116,7 +99,6 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
bytea *raw_page = PG_GETARG_BYTEA_P(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
Page page;
- GISTPageOpaque opaq;
OffsetNumber offset;
OffsetNumber maxoff = InvalidOffsetNumber;
@@ -127,29 +109,11 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
InitMaterializedSRF(fcinfo, 0);
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
PG_RETURN_NULL();
- /* verify the special space has the expected size */
- if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected special size %d, got %d.",
- (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
- (int) PageGetSpecialSize(page))));
-
- opaq = GistPageGetOpaque(page);
- if (opaq->gist_page_id != GIST_PAGE_ID)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected %08x, got %08x.",
- GIST_PAGE_ID,
- opaq->gist_page_id)));
-
/* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
if (GistPageIsDeleted(page))
elog(NOTICE, "page is deleted");
@@ -193,6 +157,40 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
return (Datum) 0;
}
+/*
+ * Verify that the given bytea contains a GIST page or die in the attempt.
+ * A pointer to the page is returned.
+ */
+static Page
+verify_gist_page(bytea *raw_page)
+{
+ Page page = get_page_from_raw(raw_page);
+ GISTPageOpaque opaq;
+
+ if (PageIsNew(page))
+ return page;
+
+ /* verify the special space has the expected size */
+ if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("input page is not a valid %s page", "GiST"),
+ errdetail("Expected special size %d, got %d.",
+ (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
+ (int) PageGetSpecialSize(page))));
+
+ opaq = GistPageGetOpaque(page);
+ if (opaq->gist_page_id != GIST_PAGE_ID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("input page is not a valid %s page", "GiST"),
+ errdetail("Expected %08x, got %08x.",
+ GIST_PAGE_ID,
+ opaq->gist_page_id)));
+
+ return page;
+}
+
Datum
gist_page_items(PG_FUNCTION_ARGS)
{
@@ -220,7 +218,7 @@ gist_page_items(PG_FUNCTION_ARGS)
errmsg("\"%s\" is not a %s index",
RelationGetRelationName(indexRel), "GiST")));
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
{
Attachments:
[text/plain] verify_gist_page.diff (5.0K, ../../38ce17fb-37d8-252b-f11d-a8fcec944086@postgrespro.ru/2-verify_gist_page.diff)
download | inline diff:
diff --git a/contrib/pageinspect/gistfuncs.c b/contrib/pageinspect/gistfuncs.c
index 100697814d..2b252f85bd 100644
--- a/contrib/pageinspect/gistfuncs.c
+++ b/contrib/pageinspect/gistfuncs.c
@@ -32,13 +32,14 @@ PG_FUNCTION_INFO_V1(gist_page_items_bytea);
#define IS_GIST(r) ((r)->rd_rel->relam == GIST_AM_OID)
+static Page verify_gist_page(bytea *raw_page);
+
Datum
gist_page_opaque_info(PG_FUNCTION_ARGS)
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
TupleDesc tupdesc;
Page page;
- GISTPageOpaque opaq;
HeapTuple resultTuple;
Datum values[4];
bool nulls[4];
@@ -51,35 +52,17 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
PG_RETURN_NULL();
- /* verify the special space has the expected size */
- if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected special size %d, got %d.",
- (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
- (int) PageGetSpecialSize(page))));
-
- opaq = GistPageGetOpaque(page);
- if (opaq->gist_page_id != GIST_PAGE_ID)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected %08x, got %08x.",
- GIST_PAGE_ID,
- opaq->gist_page_id)));
-
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
/* Convert the flags bitmask to an array of human-readable names */
- flagbits = opaq->flags;
+ flagbits = GistPageGetOpaque(page)->flags;
if (flagbits & F_LEAF)
flags[nflags++] = CStringGetTextDatum("leaf");
if (flagbits & F_DELETED)
@@ -101,7 +84,7 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
values[0] = LSNGetDatum(PageGetLSN(page));
values[1] = LSNGetDatum(GistPageGetNSN(page));
- values[2] = Int64GetDatum(opaq->rightlink);
+ values[2] = Int64GetDatum(GistPageGetOpaque(page)->rightlink);
values[3] = PointerGetDatum(construct_array_builtin(flags, nflags, TEXTOID));
/* Build and return the result tuple. */
@@ -116,7 +99,6 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
bytea *raw_page = PG_GETARG_BYTEA_P(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
Page page;
- GISTPageOpaque opaq;
OffsetNumber offset;
OffsetNumber maxoff = InvalidOffsetNumber;
@@ -127,29 +109,11 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
InitMaterializedSRF(fcinfo, 0);
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
PG_RETURN_NULL();
- /* verify the special space has the expected size */
- if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected special size %d, got %d.",
- (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
- (int) PageGetSpecialSize(page))));
-
- opaq = GistPageGetOpaque(page);
- if (opaq->gist_page_id != GIST_PAGE_ID)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("input page is not a valid %s page", "GiST"),
- errdetail("Expected %08x, got %08x.",
- GIST_PAGE_ID,
- opaq->gist_page_id)));
-
/* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
if (GistPageIsDeleted(page))
elog(NOTICE, "page is deleted");
@@ -193,6 +157,40 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
return (Datum) 0;
}
+/*
+ * Verify that the given bytea contains a GIST page or die in the attempt.
+ * A pointer to the page is returned.
+ */
+static Page
+verify_gist_page(bytea *raw_page)
+{
+ Page page = get_page_from_raw(raw_page);
+ GISTPageOpaque opaq;
+
+ if (PageIsNew(page))
+ return page;
+
+ /* verify the special space has the expected size */
+ if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GISTPageOpaqueData)))
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("input page is not a valid %s page", "GiST"),
+ errdetail("Expected special size %d, got %d.",
+ (int) MAXALIGN(sizeof(GISTPageOpaqueData)),
+ (int) PageGetSpecialSize(page))));
+
+ opaq = GistPageGetOpaque(page);
+ if (opaq->gist_page_id != GIST_PAGE_ID)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("input page is not a valid %s page", "GiST"),
+ errdetail("Expected %08x, got %08x.",
+ GIST_PAGE_ID,
+ opaq->gist_page_id)));
+
+ return page;
+}
+
Datum
gist_page_items(PG_FUNCTION_ARGS)
{
@@ -220,7 +218,7 @@ gist_page_items(PG_FUNCTION_ARGS)
errmsg("\"%s\" is not a %s index",
RelationGetRelationName(indexRel), "GiST")));
- page = get_page_from_raw(raw_page);
+ page = verify_gist_page(raw_page);
if (PageIsNew(page))
{
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-01 11:01 Michael Paquier <michael@paquier.xyz>
parent: Dmitry Koval <d.koval@postgrespro.ru>
0 siblings, 1 reply; 6+ messages in thread
From: Michael Paquier @ 2023-03-01 11:01 UTC (permalink / raw)
To: Dmitry Koval <d.koval@postgrespro.ru>; +Cc: pgsql-bugs@lists.postgresql.org
On Wed, Mar 01, 2023 at 12:31:47PM +0300, Dmitry Koval wrote:
> Attached fix for "master" branch.
SELECT gist_page_items(get_raw_page('test_gist_btree', 0), 'test_gist_idx');
So you have been mixing more than one index AM type to trigger that,
and the second argument fails already if we don't pass down a gist
index.
gist.sql has some coverage, but not for a combination like that. Like
the recent things done in this area, well, I don't see why this one
could not be plugged as well.. I'll see into it.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (832B, ../../Y%2F8wjemQkxJvvBWS@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-02 05:05 Michael Paquier <michael@paquier.xyz>
parent: Michael Paquier <michael@paquier.xyz>
0 siblings, 1 reply; 6+ messages in thread
From: Michael Paquier @ 2023-03-02 05:05 UTC (permalink / raw)
To: Dmitry Koval <d.koval@postgrespro.ru>; +Cc: pgsql-bugs@lists.postgresql.org
On Wed, Mar 01, 2023 at 08:01:33PM +0900, Michael Paquier wrote:
> gist.sql has some coverage, but not for a combination like that. Like
> the recent things done in this area, well, I don't see why this one
> could not be plugged as well.. I'll see into it.
Okay, done and backpatched. I have added a similar test for BRIN,
while on it, as it relies on a raw page and an index when listing its
items.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (832B, ../../ZAAumE8ybvMgaMyO@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-02 06:14 Dmitry Koval <d.koval@postgrespro.ru>
parent: Michael Paquier <michael@paquier.xyz>
0 siblings, 1 reply; 6+ messages in thread
From: Dmitry Koval @ 2023-03-02 06:14 UTC (permalink / raw)
To: Michael Paquier <michael@paquier.xyz>; +Cc: pgsql-bugs@lists.postgresql.org
> Okay, done and backpatched. I have added a similar test for BRIN,
> while on it, as it relies on a raw page and an index when listing its
> items.
Thank you!
--
With best regards,
Dmitry Koval
Postgres Professional: http://postgrespro.com
^ permalink raw reply [nested|flat] 6+ messages in thread
* Re: BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension
@ 2023-03-02 07:02 Michael Paquier <michael@paquier.xyz>
parent: Dmitry Koval <d.koval@postgrespro.ru>
0 siblings, 0 replies; 6+ messages in thread
From: Michael Paquier @ 2023-03-02 07:02 UTC (permalink / raw)
To: Dmitry Koval <d.koval@postgrespro.ru>; +Cc: pgsql-bugs@lists.postgresql.org
On Thu, Mar 02, 2023 at 09:14:32AM +0300, Dmitry Koval wrote:
> Thank you!
No problem. That was a nice catch.
--
Michael
Attachments:
[application/pgp-signature] signature.asc (832B, ../../ZABJ9Q8o+UN1uxs9@paquier.xyz/2-signature.asc)
download
^ permalink raw reply [nested|flat] 6+ messages in thread
end of thread, other threads:[~2023-03-02 07:02 UTC | newest]
Thread overview: 6+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2023-03-01 05:53 BUG #17815: Server crashes on executing gist_page_items() in pageinspect extension PG Bug reporting form <noreply@postgresql.org>
2023-03-01 09:31 ` Dmitry Koval <d.koval@postgrespro.ru>
2023-03-01 11:01 ` Michael Paquier <michael@paquier.xyz>
2023-03-02 05:05 ` Michael Paquier <michael@paquier.xyz>
2023-03-02 06:14 ` Dmitry Koval <d.koval@postgrespro.ru>
2023-03-02 07:02 ` Michael Paquier <michael@paquier.xyz>
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