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

Commitd3a9b83

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 parent5610411 commitd3a9b83

File tree

15 files changed

+142
-67
lines changed

15 files changed

+142
-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)
@@ -169,6 +152,13 @@ brin_page_items(PG_FUNCTION_ARGS)
169152
MemoryContextSwitchTo(oldcontext);
170153

171154
indexRel=index_open(indexRelid,AccessShareLock);
155+
156+
if (!IS_BRIN(indexRel))
157+
ereport(ERROR,
158+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
159+
errmsg("\"%s\" is not a %s index",
160+
RelationGetRelationName(indexRel),"BRIN")));
161+
172162
bdesc=brin_build_desc(indexRel);
173163

174164
/* minimally verify the page we got */

‎contrib/pageinspect/btreefuncs.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,10 @@ bt_page_stats(PG_FUNCTION_ARGS)
184184
rel=relation_openrv(relrv,AccessShareLock);
185185

186186
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
187-
elog(ERROR,"relation \"%s\" is not a btree index",
188-
RelationGetRelationName(rel));
187+
ereport(ERROR,
188+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
189+
errmsg("\"%s\" is not a %s index",
190+
RelationGetRelationName(rel),"btree")));
189191

190192
/*
191193
* Reject attempts to read non-local temporary relations; we would be
@@ -434,8 +436,10 @@ bt_page_items(PG_FUNCTION_ARGS)
434436
rel=relation_openrv(relrv,AccessShareLock);
435437

436438
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
437-
elog(ERROR,"relation \"%s\" is not a btree index",
438-
RelationGetRelationName(rel));
439+
ereport(ERROR,
440+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
441+
errmsg("\"%s\" is not a %s index",
442+
RelationGetRelationName(rel),"btree")));
439443

440444
/*
441445
* Reject attempts to read non-local temporary relations; we would be
@@ -522,7 +526,6 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
522526
Datumresult;
523527
FuncCallContext*fctx;
524528
structuser_args*uargs;
525-
intraw_page_size;
526529

527530
if (!superuser())
528531
ereport(ERROR,
@@ -535,19 +538,12 @@ bt_page_items_bytea(PG_FUNCTION_ARGS)
535538
MemoryContextmctx;
536539
TupleDesctupleDesc;
537540

538-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
539-
540-
if (raw_page_size<SizeOfPageHeaderData)
541-
ereport(ERROR,
542-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
543-
errmsg("input page too small (%d bytes)",raw_page_size)));
544-
545541
fctx=SRF_FIRSTCALL_INIT();
546542
mctx=MemoryContextSwitchTo(fctx->multi_call_memory_ctx);
547543

548544
uargs=palloc(sizeof(structuser_args));
549545

550-
uargs->page=VARDATA(raw_page);
546+
uargs->page=get_page_from_raw(raw_page);
551547

552548
uargs->offset=FirstOffsetNumber;
553549

@@ -625,8 +621,10 @@ bt_metap(PG_FUNCTION_ARGS)
625621
rel=relation_openrv(relrv,AccessShareLock);
626622

627623
if (!IS_INDEX(rel)|| !IS_BTREE(rel))
628-
elog(ERROR,"relation \"%s\" is not a btree index",
629-
RelationGetRelationName(rel));
624+
ereport(ERROR,
625+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
626+
errmsg("\"%s\" is not a %s index",
627+
RelationGetRelationName(rel),"btree")));
630628

631629
/*
632630
* 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
@@ -64,4 +64,19 @@ tids |
6464

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

‎contrib/pageinspect/expected/gin.out

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

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

‎contrib/pageinspect/expected/hash.out

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

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

‎contrib/pageinspect/expected/page.out

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

203203
drop table test8;
204+
-- Failure with incorrect page size
205+
-- Suppress the DETAIL message, to allow the tests to work across various
206+
-- page sizes.
207+
\set VERBOSITY terse
208+
SELECT fsm_page_contents('aaa'::bytea);
209+
ERROR: invalid page size
210+
SELECT page_checksum('bbb'::bytea, 0);
211+
ERROR: invalid page size
212+
SELECT page_header('ccc'::bytea);
213+
ERROR: invalid page size
214+
\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/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
@@ -218,7 +218,6 @@ Datum
218218
page_header(PG_FUNCTION_ARGS)
219219
{
220220
bytea*raw_page=PG_GETARG_BYTEA_P(0);
221-
intraw_page_size;
222221

223222
TupleDesctupdesc;
224223

@@ -235,18 +234,7 @@ page_header(PG_FUNCTION_ARGS)
235234
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
236235
errmsg("must be superuser to use raw page functions")));
237236

238-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
239-
240-
/*
241-
* Check that enough data was supplied, so that we don't try to access
242-
* fields outside the supplied buffer.
243-
*/
244-
if (raw_page_size<SizeOfPageHeaderData)
245-
ereport(ERROR,
246-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
247-
errmsg("input page too small (%d bytes)",raw_page_size)));
248-
249-
page= (PageHeader)VARDATA(raw_page);
237+
page= (PageHeader)get_page_from_raw(raw_page);
250238

251239
/* Build a tuple descriptor for our result type */
252240
if (get_call_result_type(fcinfo,NULL,&tupdesc)!=TYPEFUNC_COMPOSITE)
@@ -299,25 +287,14 @@ page_checksum(PG_FUNCTION_ARGS)
299287
{
300288
bytea*raw_page=PG_GETARG_BYTEA_P(0);
301289
uint32blkno=PG_GETARG_INT32(1);
302-
intraw_page_size;
303-
PageHeaderpage;
290+
Pagepage;
304291

305292
if (!superuser())
306293
ereport(ERROR,
307294
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
308295
errmsg("must be superuser to use raw page functions")));
309296

310-
raw_page_size=VARSIZE(raw_page)-VARHDRSZ;
311-
312-
/*
313-
* Check that the supplied page is of the right size.
314-
*/
315-
if (raw_page_size!=BLCKSZ)
316-
ereport(ERROR,
317-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
318-
errmsg("incorrect size of input page (%d bytes)",raw_page_size)));
319-
320-
page= (PageHeader)VARDATA(raw_page);
297+
page=get_page_from_raw(raw_page);
321298

322299
PG_RETURN_INT16(pg_checksum_page((char*)page,blkno));
323300
}

‎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
@@ -18,4 +18,17 @@ SELECT * FROM bt_page_items(get_raw_page('test1_a_idx', 0));
1818
SELECT*FROM bt_page_items(get_raw_page('test1_a_idx',1));
1919
SELECT*FROM bt_page_items(get_raw_page('test1_a_idx',2));
2020

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

‎contrib/pageinspect/sql/gin.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ SELECT COUNT(*) > 0
1717
FROM gin_leafpage_items(get_raw_page('test1_y_idx',
1818
(pg_relation_size('test1_y_idx')/
1919
current_setting('block_size')::bigint)::int-1));
20+
21+
-- Failure with incorrect page size
22+
-- Suppress the DETAIL message, to allow the tests to work across various
23+
-- page sizes.
24+
\set VERBOSITY terse
25+
SELECT gin_leafpage_items('aaa'::bytea);
26+
SELECT gin_metapage_info('bbb'::bytea);
27+
SELECT gin_page_opaque_info('ccc'::bytea);
28+
\set VERBOSITY default

‎contrib/pageinspect/sql/hash.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,18 @@ SELECT * FROM hash_page_items(get_raw_page('test_hash_a_idx', 3));
7676
SELECT*FROM hash_page_items(get_raw_page('test_hash_a_idx',4));
7777
SELECT*FROM hash_page_items(get_raw_page('test_hash_a_idx',5));
7878

79+
-- Failure with non-hash index
80+
CREATEINDEXtest_hash_a_btreeON test_hash USING btree (a);
81+
SELECT hash_bitmap_info('test_hash_a_btree',0);
82+
83+
-- Failure with incorrect page size
84+
-- Suppress the DETAIL message, to allow the tests to work across various
85+
-- page sizes.
86+
\set VERBOSITY terse
87+
SELECT hash_metapage_info('aaa'::bytea);
88+
SELECT hash_page_items('bbb'::bytea);
89+
SELECT hash_page_stats('ccc'::bytea);
90+
SELECT hash_page_type('ddd'::bytea);
91+
\set VERBOSITY default
7992

8093
DROPTABLE test_hash;

‎contrib/pageinspect/sql/page.sql

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,12 @@ select t_bits, t_data from heap_page_items(get_raw_page('test8', 0));
8080
select tuple_data_split('test8'::regclass, t_data, t_infomask, t_infomask2, t_bits)
8181
from heap_page_items(get_raw_page('test8',0));
8282
droptable test8;
83+
84+
-- Failure with incorrect page size
85+
-- Suppress the DETAIL message, to allow the tests to work across various
86+
-- page sizes.
87+
\set VERBOSITY terse
88+
SELECT fsm_page_contents('aaa'::bytea);
89+
SELECT page_checksum('bbb'::bytea,0);
90+
SELECT page_header('ccc'::bytea);
91+
\set VERBOSITY default

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp