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

Commit076f4d9

Browse files
committed
pageinspect: Fix handling of page sizes and AM types
This commit fixes a set of issues related to the use of the SQLfunctions in this module when the caller is able to pass down raw pagedata as input argument:- The page size check was fuzzy in a couple of places, sometimeslooking after only a sub-range, but what we are looking for is an exactmatch on BLCKSZ. After considering a few options here, I have settleddown to do a generalization of get_page_from_raw(). Most of the SQLfunctions already used that, and this is not strictly required if notaccessing an 8-byte-wide value from a raw page, but this feels safer inthe long run for alignment-picky environment, particularly if a codepath begins to access such values. This also reduces the number ofstrings that need to be translated.- The BRIN function brin_page_items() uses a Relation but it did notcheck the access method of the opened index, potentially leading tocrashes. All the other functions in need of a Relation already didthat.- Some code paths could fail on elog(), but we should to use ereport()for failures that can be triggered by the user.Tests are added to stress all the cases that are fixed as of thiscommit, with some junk raw pages (\set VERBOSITY ensures that this worksacross all page sizes) and unexpected index types when functions openrelations.Author: Michael Paquier, Justin PrysbyDiscussion:https://postgr.es/m/20220218030020.GA1137@telsasoft.comBackpatch-through: 10
1 parent5e6368b commit076f4d9

File tree

18 files changed

+179
-67
lines changed

18 files changed

+179
-67
lines changed

‎contrib/pageinspect/brinfuncs.c

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include"access/brin_tuple.h"
1717
#include"access/htup_details.h"
1818
#include"catalog/index.h"
19+
#include"catalog/pg_am_d.h"
1920
#include"catalog/pg_type.h"
2021
#include"funcapi.h"
2122
#include"lib/stringinfo.h"
@@ -31,6 +32,8 @@ PG_FUNCTION_INFO_V1(brin_page_items);
3132
PG_FUNCTION_INFO_V1(brin_metapage_info);
3233
PG_FUNCTION_INFO_V1(brin_revmap_data);
3334

35+
#defineIS_BRIN(r) ((r)->rd_rel->relam == BRIN_AM_OID)
36+
3437
typedefstructbrin_column_state
3538
{
3639
intnstored;
@@ -45,23 +48,15 @@ Datum
4548
brin_page_type(PG_FUNCTION_ARGS)
4649
{
4750
bytea*raw_page=PG_GETARG_BYTEA_P(0);
48-
Pagepage=VARDATA(raw_page);
49-
intraw_page_size;
51+
Pagepage;
5052
char*type;
5153

5254
if (!superuser())
5355
ereport(ERROR,
5456
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
5557
errmsg("must be superuser to use raw page functions")));
5658

57-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
58-
59-
if (raw_page_size!=BLCKSZ)
60-
ereport(ERROR,
61-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
62-
errmsg("input page too small"),
63-
errdetail("Expected size %d, got %d",
64-
BLCKSZ,raw_page_size)));
59+
page=get_page_from_raw(raw_page);
6560

6661
switch (BrinPageType(page))
6762
{
@@ -89,19 +84,7 @@ brin_page_type(PG_FUNCTION_ARGS)
8984
staticPage
9085
verify_brin_page(bytea*raw_page,uint16type,constchar*strtype)
9186
{
92-
Pagepage;
93-
intraw_page_size;
94-
95-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
96-
97-
if (raw_page_size!=BLCKSZ)
98-
ereport(ERROR,
99-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
100-
errmsg("input page too small"),
101-
errdetail("Expected size %d, got %d",
102-
BLCKSZ,raw_page_size)));
103-
104-
page=VARDATA(raw_page);
87+
Pagepage=get_page_from_raw(raw_page);
10588

10689
/* verify the special space says this page is what we want */
10790
if (BrinPageType(page)!=type)
@@ -143,6 +126,13 @@ brin_page_items(PG_FUNCTION_ARGS)
143126
SetSingleFuncCall(fcinfo,0);
144127

145128
indexRel=index_open(indexRelid,AccessShareLock);
129+
130+
if (!IS_BRIN(indexRel))
131+
ereport(ERROR,
132+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
133+
errmsg("\"%s\" is not a %s index",
134+
RelationGetRelationName(indexRel),"BRIN")));
135+
146136
bdesc=brin_build_desc(indexRel);
147137

148138
/* minimally verify the page we got */

‎contrib/pageinspect/btreefuncs.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,10 @@ bt_page_stats_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
206206
rel=relation_openrv(relrv,AccessShareLock);
207207

208208
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
209-
elog(ERROR,"relation \"%s\" is not a btree index",
210-
RelationGetRelationName(rel));
209+
ereport(ERROR,
210+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
211+
errmsg("\"%s\" is not a %s index",
212+
RelationGetRelationName(rel),"btree")));
211213

212214
/*
213215
* Reject attempts to read non-local temporary relations; we would be
@@ -476,8 +478,10 @@ bt_page_items_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
476478
rel=relation_openrv(relrv,AccessShareLock);
477479

478480
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
479-
elog(ERROR,"relation \"%s\" is not a btree index",
480-
RelationGetRelationName(rel));
481+
ereport(ERROR,
482+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
483+
errmsg("\"%s\" is not a %s index",
484+
RelationGetRelationName(rel),"btree")));
481485

482486
/*
483487
* Reject attempts to read non-local temporary relations; we would be
@@ -588,7 +592,6 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
588592
Datumresult;
589593
FuncCallContext*fctx;
590594
structuser_args*uargs;
591-
intraw_page_size;
592595

593596
if (!superuser())
594597
ereport(ERROR,
@@ -601,19 +604,12 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
601604
MemoryContextmctx;
602605
TupleDesctupleDesc;
603606

604-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
605-
606-
if (raw_page_size<SizeOfPageHeaderData)
607-
ereport(ERROR,
608-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
609-
errmsg("input page too small (%d bytes)",raw_page_size)));
610-
611607
fctx=SRF_FIRSTCALL_INIT();
612608
mctx=MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
613609

614610
uargs=palloc(sizeof(structuser_args));
615611

616-
uargs->page=VARDATA(raw_page);
612+
uargs->page=get_page_from_raw(raw_page);
617613

618614
uargs->offset=FirstOffsetNumber;
619615

@@ -698,8 +694,10 @@ bt_metap(PG_FUNCTION_ARGS)
698694
rel=relation_openrv(relrv,AccessShareLock);
699695

700696
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
701-
elog(ERROR,"relation \"%s\" is not a btree index",
702-
RelationGetRelationName(rel));
697+
ereport(ERROR,
698+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
699+
errmsg("\"%s\" is not a %s index",
700+
RelationGetRelationName(rel),"btree")));
703701

704702
/*
705703
* Reject attempts to read non-local temporary relations; we would be

‎contrib/pageinspect/expected/brin.out

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,8 @@ 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.
52+
CREATE INDEX test1_a_btree ON test1 (a);
53+
SELECT brin_page_items(get_raw_page('test1_a_btree', 0), 'test1_a_btree');
54+
ERROR: "test1_a_btree" is not a BRIN index
5155
DROP TABLE test1;

‎contrib/pageinspect/expected/btree.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,19 @@ tids |
7070

7171
SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 2));
7272
ERROR: block number 2 is out of range for relation "test1_a_idx"
73+
-- Failure when using a non-btree index.
74+
CREATE INDEX test1_a_hash ON test1 USING hash(a);
75+
SELECT bt_metap('test1_a_hash');
76+
ERROR: "test1_a_hash" is not a btree index
77+
SELECT bt_page_stats('test1_a_hash', 0);
78+
ERROR: "test1_a_hash" is not a btree index
79+
SELECT bt_page_items('test1_a_hash', 0);
80+
ERROR: "test1_a_hash" is not a btree index
81+
-- Failure with incorrect page size
82+
-- Suppress the DETAIL message, to allow the tests to work across various
83+
-- page sizes.
84+
\set VERBOSITY terse
85+
SELECT bt_page_items('aaa'::bytea);
86+
ERROR: invalid page size
87+
\set VERBOSITY default
7388
DROP TABLE test1;

‎contrib/pageinspect/expected/gin.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,14 @@ FROM gin_leafpage_items(get_raw_page('test1_y_idx',
3636
?column? | t
3737

3838
DROP TABLE test1;
39+
-- Failure with incorrect page size
40+
-- Suppress the DETAIL message, to allow the tests to work across various
41+
-- page sizes.
42+
\set VERBOSITY terse
43+
SELECT gin_leafpage_items('aaa'::bytea);
44+
ERROR: invalid page size
45+
SELECT gin_metapage_info('bbb'::bytea);
46+
ERROR: invalid page size
47+
SELECT gin_page_opaque_info('ccc'::bytea);
48+
ERROR: invalid page size
49+
\set VERBOSITY default

‎contrib/pageinspect/expected/gist.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,19 @@ SELECT itemoffset, ctid, itemlen FROM gist_page_items_bytea(get_raw_page('test_g
6464
6 | (6,65535) | 40
6565
(6 rows)
6666

67+
-- Failure with non-GiST index.
68+
CREATE INDEX test_gist_btree on test_gist(t);
69+
SELECT gist_page_items(get_raw_page('test_gist_btree', 0), 'test_gist_btree');
70+
ERROR: "test_gist_btree" is not a GiST index
71+
-- Failure with incorrect page size
72+
-- Suppress the DETAIL message, to allow the tests to work across various
73+
-- page sizes.
74+
\set VERBOSITY terse
75+
SELECT gist_page_items_bytea('aaa'::bytea);
76+
ERROR: invalid page size
77+
SELECT gist_page_items('aaa'::bytea, 'test_gist_idx'::regclass);
78+
ERROR: invalid page size
79+
SELECT gist_page_opaque_info('aaa'::bytea);
80+
ERROR: invalid page size
81+
\set VERBOSITY default
6782
DROP TABLE test_gist;

‎contrib/pageinspect/expected/hash.out

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,21 @@ SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 4));
163163

164164
SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 5));
165165
ERROR: page is not a hash bucket or overflow page
166+
-- Failure with non-hash index
167+
CREATE INDEX test_hash_a_btree ON test_hash USING btree (a);
168+
SELECT hash_bitmap_info('test_hash_a_btree', 0);
169+
ERROR: "test_hash_a_btree" is not a hash index
170+
-- Failure with incorrect page size
171+
-- Suppress the DETAIL message, to allow the tests to work across various
172+
-- page sizes.
173+
\set VERBOSITY terse
174+
SELECT hash_metapage_info('aaa'::bytea);
175+
ERROR: invalid page size
176+
SELECT hash_page_items('bbb'::bytea);
177+
ERROR: invalid page size
178+
SELECT hash_page_stats('ccc'::bytea);
179+
ERROR: invalid page size
180+
SELECT hash_page_type('ddd'::bytea);
181+
ERROR: invalid page size
182+
\set VERBOSITY default
166183
DROP TABLE test_hash;

‎contrib/pageinspect/expected/page.out

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,14 @@ select tuple_data_split('test8'::regclass, t_data, t_infomask, t_infomask2, t_bi
207207
(1 row)
208208

209209
drop table test8;
210+
-- Failure with incorrect page size
211+
-- Suppress the DETAIL message, to allow the tests to work across various
212+
-- page sizes.
213+
\set VERBOSITY terse
214+
SELECT fsm_page_contents('aaa'::bytea);
215+
ERROR: invalid page size
216+
SELECT page_checksum('bbb'::bytea, 0);
217+
ERROR: invalid page size
218+
SELECT page_header('ccc'::bytea);
219+
ERROR: invalid page size
220+
\set VERBOSITY default

‎contrib/pageinspect/fsmfuncs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ fsm_page_contents(PG_FUNCTION_ARGS)
3636
{
3737
bytea*raw_page=PG_GETARG_BYTEA_P(0);
3838
StringInfoDatasinfo;
39+
Pagepage;
3940
FSMPagefsmpage;
4041
inti;
4142

@@ -44,7 +45,8 @@ fsm_page_contents(PG_FUNCTION_ARGS)
4445
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
4546
errmsg("must be superuser to use raw page functions")));
4647

47-
fsmpage= (FSMPage)PageGetContents(VARDATA(raw_page));
48+
page=get_page_from_raw(raw_page);
49+
fsmpage= (FSMPage)PageGetContents(page);
4850

4951
initStringInfo(&sinfo);
5052

‎contrib/pageinspect/gistfuncs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include"access/htup.h"
1515
#include"access/relation.h"
1616
#include"catalog/namespace.h"
17+
#include"catalog/pg_am_d.h"
1718
#include"funcapi.h"
1819
#include"miscadmin.h"
1920
#include"pageinspect.h"
@@ -28,6 +29,8 @@ PG_FUNCTION_INFO_V1(gist_page_opaque_info);
2829
PG_FUNCTION_INFO_V1(gist_page_items);
2930
PG_FUNCTION_INFO_V1(gist_page_items_bytea);
3031

32+
#defineIS_GIST(r) ((r)->rd_rel->relam == GIST_AM_OID)
33+
3134
#defineItemPointerGetDatum(X) PointerGetDatum(X)
3235

3336

@@ -174,6 +177,12 @@ gist_page_items(PG_FUNCTION_ARGS)
174177
/* Open the relation */
175178
indexRel=index_open(indexRelid,AccessShareLock);
176179

180+
if (!IS_GIST(indexRel))
181+
ereport(ERROR,
182+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
183+
errmsg("\"%s\" is not a %s index",
184+
RelationGetRelationName(indexRel),"GiST")));
185+
177186
page=get_page_from_raw(raw_page);
178187

179188
/* Avoid bogus PageGetMaxOffsetNumber() call with deleted pages */

‎contrib/pageinspect/hashfuncs.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,10 @@ hash_bitmap_info(PG_FUNCTION_ARGS)
417417
indexRel=index_open(indexRelid,AccessShareLock);
418418

419419
if (!IS_HASH(indexRel))
420-
elog(ERROR,"relation \"%s\" is not a hash index",
421-
RelationGetRelationName(indexRel));
420+
ereport(ERROR,
421+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
422+
errmsg("\"%s\" is not a %s index",
423+
RelationGetRelationName(indexRel),"hash")));
422424

423425
if (RELATION_IS_OTHER_TEMP(indexRel))
424426
ereport(ERROR,

‎contrib/pageinspect/rawpage.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,6 @@ Datum
246246
page_header(PG_FUNCTION_ARGS)
247247
{
248248
bytea*raw_page=PG_GETARG_BYTEA_P(0);
249-
intraw_page_size;
250249

251250
TupleDesctupdesc;
252251

@@ -263,18 +262,7 @@ page_header(PG_FUNCTION_ARGS)
263262
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
264263
errmsg("must be superuser to use raw page functions")));
265264

266-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
267-
268-
/*
269-
* Check that enough data was supplied, so that we don't try to access
270-
* fields outside the supplied buffer.
271-
*/
272-
if (raw_page_size<SizeOfPageHeaderData)
273-
ereport(ERROR,
274-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
275-
errmsg("input page too small (%d bytes)",raw_page_size)));
276-
277-
page= (PageHeader)VARDATA(raw_page);
265+
page= (PageHeader)get_page_from_raw(raw_page);
278266

279267
/* Build a tuple descriptor for our result type */
280268
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
@@ -350,8 +338,7 @@ page_checksum_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
350338
{
351339
bytea*raw_page=PG_GETARG_BYTEA_P(0);
352340
int64blkno= (ext_version==PAGEINSPECT_V1_8 ?PG_GETARG_UINT32(1) :PG_GETARG_INT64(1));
353-
intraw_page_size;
354-
PageHeaderpage;
341+
Pagepage;
355342

356343
if (!superuser())
357344
ereport(ERROR,
@@ -363,17 +350,7 @@ page_checksum_internal(PG_FUNCTION_ARGS, enum pageinspect_version ext_version)
363350
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
364351
errmsg("invalid block number")));
365352

366-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
367-
368-
/*
369-
* Check that the supplied page is of the right size.
370-
*/
371-
if (raw_page_size!=BLCKSZ)
372-
ereport(ERROR,
373-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
374-
errmsg("incorrect size of input page (%d bytes)",raw_page_size)));
375-
376-
page= (PageHeader)VARDATA(raw_page);
353+
page=get_page_from_raw(raw_page);
377354

378355
PG_RETURN_INT16(pg_checksum_page((char*)page,blkno));
379356
}

‎contrib/pageinspect/sql/brin.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ 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.
19+
CREATEINDEXtest1_a_btreeON test1 (a);
20+
SELECT brin_page_items(get_raw_page('test1_a_btree',0),'test1_a_btree');
21+
1822
DROPTABLE test1;

‎contrib/pageinspect/sql/btree.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,17 @@ SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 0));
2121
SELECT*FROM bt_page_items(get_raw_page('test1_a_idx',1));
2222
SELECT*FROM bt_page_items(get_raw_page('test1_a_idx',2));
2323

24+
-- Failure when using a non-btree index.
25+
CREATEINDEXtest1_a_hashON test1 USING hash(a);
26+
SELECT bt_metap('test1_a_hash');
27+
SELECT bt_page_stats('test1_a_hash',0);
28+
SELECT bt_page_items('test1_a_hash',0);
29+
30+
-- Failure with incorrect page size
31+
-- Suppress the DETAIL message, to allow the tests to work across various
32+
-- page sizes.
33+
\set VERBOSITY terse
34+
SELECT bt_page_items('aaa'::bytea);
35+
\set VERBOSITY default
36+
2437
DROPTABLE test1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp