Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5ad63ee

Browse files
committed
pageinspect: Fix crash with gist_page_items()
Attempting to use this function with a raw page not coming from a GiSTindex would cause a crash, as it was missing the same sanity checks asgist_page_items_bytea(). This slightly refactors the code so as all thebasic validation checks for GiST pages are done in a single routine,in the same fashion as the pageinspect functions for hash and BRIN.This fixes an issue similar to076f4d9. A test is added to stress forthis case. While on it, I have added a similar test forbrin_page_items() with a combination make of a valid GiST index and araw btree page. This one was already protected, but it was not tested.Reported-by: Egor ChindyaskinAuthor: Dmitry KovalDiscussion:https://postgr.es/m/17815-fc4a2d3b74705703@postgresql.orgBackpatch-through: 14
1 parent1a9356f commit5ad63ee

File tree

5 files changed

+62
-56
lines changed

5 files changed

+62
-56
lines changed

‎contrib/pageinspect/expected/brin.out

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,14 @@ SELECT * FROM brin_page_items(get_raw_page('test1_a_idx', 2), 'test1_a_idx')
4848
1 | 0 | 1 | f | f | f | {1 .. 1}
4949
(1 row)
5050

51-
-- Failure for non-BRIN index.
51+
-- Mask DETAIL messages as these are not portable across architectures.
52+
\set VERBOSITY terse
53+
-- Failures for non-BRIN index.
5254
CREATE INDEX test1_a_btree ON test1 (a);
5355
SELECT brin_page_items(get_raw_page('test1_a_btree', 0), 'test1_a_btree');
5456
ERROR: "test1_a_btree" is not a BRIN index
55-
-- Mask DETAIL messages as these are not portable across architectures.
56-
\set VERBOSITY terse
57+
SELECT brin_page_items(get_raw_page('test1_a_btree', 0), 'test1_a_idx');
58+
ERROR: input page is not a valid BRIN page
5759
-- Invalid special area size
5860
SELECT brin_page_type(get_raw_page('test1', 0));
5961
ERROR: input page is not a valid BRIN page

‎contrib/pageinspect/expected/gist.out

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,16 @@ SELECT itemoffset, ctid, itemlen FROM gist_page_items_bytea(get_raw_page('test_g
6666
7 | (7,65535) | 40
6767
(7 rows)
6868

69-
-- Failure with non-GiST index.
69+
-- Suppress the DETAIL message, to allow the tests to work across various
70+
-- page sizes and architectures.
71+
\set VERBOSITY terse
72+
-- Failures with non-GiST index.
7073
CREATE INDEX test_gist_btree on test_gist(t);
7174
SELECT gist_page_items(get_raw_page('test_gist_btree', 0), 'test_gist_btree');
7275
ERROR: "test_gist_btree" is not a GiST index
76+
SELECT gist_page_items(get_raw_page('test_gist_btree', 0), 'test_gist_idx');
77+
ERROR: input page is not a valid GiST page
7378
-- Failure with various modes.
74-
-- Suppress the DETAIL message, to allow the tests to work across various
75-
-- page sizes and architectures.
76-
\set VERBOSITY terse
7779
-- invalid page size
7880
SELECT gist_page_items_bytea('aaa'::bytea);
7981
ERROR: invalid page size

‎contrib/pageinspect/gistfuncs.c

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -34,29 +34,20 @@ PG_FUNCTION_INFO_V1(gist_page_items_bytea);
3434
#defineItemPointerGetDatum(X) PointerGetDatum(X)
3535

3636

37-
Datum
38-
gist_page_opaque_info(PG_FUNCTION_ARGS)
37+
staticPageverify_gist_page(bytea*raw_page);
38+
39+
/*
40+
* Verify that the given bytea contains a GIST page or die in the attempt.
41+
* A pointer to the page is returned.
42+
*/
43+
staticPage
44+
verify_gist_page(bytea*raw_page)
3945
{
40-
bytea*raw_page=PG_GETARG_BYTEA_P(0);
41-
TupleDesctupdesc;
42-
Pagepage;
46+
Pagepage=get_page_from_raw(raw_page);
4347
GISTPageOpaqueopaq;
44-
HeapTupleresultTuple;
45-
Datumvalues[4];
46-
boolnulls[4];
47-
Datumflags[16];
48-
intnflags=0;
49-
uint16flagbits;
50-
51-
if (!superuser())
52-
ereport(ERROR,
53-
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
54-
errmsg("must be superuser to use raw page functions")));
55-
56-
page=get_page_from_raw(raw_page);
5748

5849
if (PageIsNew(page))
59-
PG_RETURN_NULL();
50+
returnpage;
6051

6152
/* verify the special space has the expected size */
6253
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GISTPageOpaqueData)))
@@ -76,12 +67,38 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
7667
GIST_PAGE_ID,
7768
opaq->gist_page_id)));
7869

70+
returnpage;
71+
}
72+
73+
Datum
74+
gist_page_opaque_info(PG_FUNCTION_ARGS)
75+
{
76+
bytea*raw_page=PG_GETARG_BYTEA_P(0);
77+
TupleDesctupdesc;
78+
Pagepage;
79+
HeapTupleresultTuple;
80+
Datumvalues[4];
81+
boolnulls[4];
82+
Datumflags[16];
83+
intnflags=0;
84+
uint16flagbits;
85+
86+
if (!superuser())
87+
ereport(ERROR,
88+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
89+
errmsg("must be superuser to use raw page functions")));
90+
91+
page=verify_gist_page(raw_page);
92+
93+
if (PageIsNew(page))
94+
PG_RETURN_NULL();
95+
7996
/* Build a tuple descriptor for our result type */
8097
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
8198
elog(ERROR,"return type must be a row type");
8299

83100
/* Convert the flags bitmask to an array of human-readable names */
84-
flagbits=opaq->flags;
101+
flagbits=GistPageGetOpaque(page)->flags;
85102
if (flagbits&F_LEAF)
86103
flags[nflags++]=CStringGetTextDatum("leaf");
87104
if (flagbits&F_DELETED)
@@ -103,7 +120,7 @@ gist_page_opaque_info(PG_FUNCTION_ARGS)
103120

104121
values[0]=LSNGetDatum(PageGetLSN(page));
105122
values[1]=LSNGetDatum(GistPageGetNSN(page));
106-
values[2]=Int64GetDatum(opaq->rightlink);
123+
values[2]=Int64GetDatum(GistPageGetOpaque(page)->rightlink);
107124
values[3]=PointerGetDatum(construct_array(flags,nflags,
108125
TEXTOID,
109126
-1, false,TYPALIGN_INT));
@@ -124,7 +141,6 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
124141
Tuplestorestate*tupstore;
125142
MemoryContextoldcontext;
126143
Pagepage;
127-
GISTPageOpaqueopaq;
128144
OffsetNumberoffset;
129145
OffsetNumbermaxoff=InvalidOffsetNumber;
130146

@@ -157,29 +173,11 @@ gist_page_items_bytea(PG_FUNCTION_ARGS)
157173

158174
MemoryContextSwitchTo(oldcontext);
159175

160-
page=get_page_from_raw(raw_page);
176+
page=verify_gist_page(raw_page);
161177

162178
if (PageIsNew(page))
163179
PG_RETURN_NULL();
164180

165-
/* verify the special space has the expected size */
166-
if (PageGetSpecialSize(page)!=MAXALIGN(sizeof(GISTPageOpaqueData)))
167-
ereport(ERROR,
168-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
169-
errmsg("input page is not a valid %s page","GiST"),
170-
errdetail("Expected special size %d, got %d.",
171-
(int)MAXALIGN(sizeof(GISTPageOpaqueData)),
172-
(int)PageGetSpecialSize(page))));
173-
174-
opaq= (GISTPageOpaque)PageGetSpecialPointer(page);
175-
if (opaq->gist_page_id!=GIST_PAGE_ID)
176-
ereport(ERROR,
177-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
178-
errmsg("input page is not a valid %s page","GiST"),
179-
errdetail("Expected %08x, got %08x.",
180-
GIST_PAGE_ID,
181-
opaq->gist_page_id)));
182-
183181
/* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */
184182
if (GistPageIsDeleted(page))
185183
elog(NOTICE,"page is deleted");
@@ -276,7 +274,7 @@ gist_page_items(PG_FUNCTION_ARGS)
276274
errmsg("\"%s\" is not a %s index",
277275
RelationGetRelationName(indexRel),"GiST")));
278276

279-
page=get_page_from_raw(raw_page);
277+
page=verify_gist_page(raw_page);
280278

281279
if (PageIsNew(page))
282280
{

‎contrib/pageinspect/sql/brin.sql

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ SELECT * FROM brin_revmap_data(get_raw_page('test1_a_idx', 1)) LIMIT 5;
1515
SELECT*FROM brin_page_items(get_raw_page('test1_a_idx',2),'test1_a_idx')
1616
ORDER BY blknum, attnumLIMIT5;
1717

18-
-- Failure for non-BRIN index.
18+
-- Mask DETAIL messages as these are not portable across architectures.
19+
\set VERBOSITY terse
20+
21+
-- Failures for non-BRIN index.
1922
CREATEINDEXtest1_a_btreeON test1 (a);
2023
SELECT brin_page_items(get_raw_page('test1_a_btree',0),'test1_a_btree');
24+
SELECT brin_page_items(get_raw_page('test1_a_btree',0),'test1_a_idx');
2125

22-
-- Mask DETAIL messages as these are not portable across architectures.
23-
\set VERBOSITY terse
2426
-- Invalid special area size
2527
SELECT brin_page_type(get_raw_page('test1',0));
2628
SELECT*FROM brin_metapage_info(get_raw_page('test1',0));

‎contrib/pageinspect/sql/gist.sql

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,16 @@ SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 1), 'test_gist_idx')
2626
-- platform-dependent (endianess), so omit the actual key data from the output.
2727
SELECT itemoffset, ctid, itemlenFROM gist_page_items_bytea(get_raw_page('test_gist_idx',0));
2828

29-
-- Failure with non-GiST index.
29+
-- Suppress the DETAIL message, to allow the tests to work across various
30+
-- page sizes and architectures.
31+
\set VERBOSITY terse
32+
33+
-- Failures with non-GiST index.
3034
CREATEINDEXtest_gist_btreeon test_gist(t);
3135
SELECT gist_page_items(get_raw_page('test_gist_btree',0),'test_gist_btree');
36+
SELECT gist_page_items(get_raw_page('test_gist_btree',0),'test_gist_idx');
3237

3338
-- Failure with various modes.
34-
-- Suppress the DETAIL message, to allow the tests to work across various
35-
-- page sizes and architectures.
36-
\set VERBOSITY terse
3739
-- invalid page size
3840
SELECT gist_page_items_bytea('aaa'::bytea);
3941
SELECT gist_page_items('aaa'::bytea,'test_gist_idx'::regclass);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp