Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 14e9b18

Browse files
committed
In pageinspect/hashfuncs.c, avoid crashes on alignment-picky machines.
On machines with MAXALIGN = 8, the payload of a bytea is not maxaligned, since it will start 4 bytes into a palloc'd value. On alignment-picky hardware, this will cause failures in accesses to 8-byte-wide values within the page. We already encountered this problem when we introduced GIN index inspection functions, and fixed it in commit 84ad68d. Make use of the same function for hash indexes. A small difficulty is that up to now contrib/pageinspect has not shared any functions at all across files. To support that, introduce a common header file "pageinspect.h" for the module. Also, move get_page_from_raw() out of ginfuncs.c, where it didn't especially belong, and put it in rawpage.c which seems a more natural home. Per buildfarm. Discussion: https://postgr.es/m/17311.1486134714@sss.pgh.pa.us
1 parent 29e312b commit 14e9b18

File tree

8 files changed

+73
-34
lines changed

8 files changed

+73
-34
lines changed

contrib/pageinspect/brinfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*/
1010
#include "postgres.h"
1111

12+
#include "pageinspect.h"
13+
1214
#include "access/htup_details.h"
1315
#include "access/brin.h"
1416
#include "access/brin_internal.h"

contrib/pageinspect/btreefuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include "postgres.h"
2929

30+
#include "pageinspect.h"
31+
3032
#include "access/nbtree.h"
3133
#include "catalog/namespace.h"
3234
#include "catalog/pg_am.h"

contrib/pageinspect/fsmfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "postgres.h"
2121

22+
#include "pageinspect.h"
23+
2224
#include "funcapi.h"
2325
#include "lib/stringinfo.h"
2426
#include "miscadmin.h"

contrib/pageinspect/ginfuncs.c

+2-20
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
*/
1010
#include "postgres.h"
1111

12+
#include "pageinspect.h"
13+
1214
#include "access/gin.h"
1315
#include "access/gin_private.h"
1416
#include "access/htup_details.h"
@@ -29,26 +31,6 @@ PG_FUNCTION_INFO_V1(gin_page_opaque_info);
2931
PG_FUNCTION_INFO_V1(gin_leafpage_items);
3032

3133

32-
static Page
33-
get_page_from_raw(bytea *raw_page)
34-
{
35-
int raw_page_size;
36-
Page page;
37-
38-
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
39-
if (raw_page_size < BLCKSZ)
40-
ereport(ERROR,
41-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
42-
errmsg("input page too small (%d bytes)", raw_page_size)));
43-
44-
/* make a copy so that the page is properly aligned for struct access */
45-
page = palloc(raw_page_size);
46-
memcpy(page, VARDATA(raw_page), raw_page_size);
47-
48-
return page;
49-
}
50-
51-
5234
Datum
5335
gin_metapage_info(PG_FUNCTION_ARGS)
5436
{

contrib/pageinspect/hashfuncs.c

+4-14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include "postgres.h"
1212

13+
#include "pageinspect.h"
14+
1315
#include "access/hash.h"
1416
#include "access/htup_details.h"
1517
#include "catalog/pg_type.h"
@@ -48,27 +50,15 @@ typedef struct HashPageStat
4850

4951
/*
5052
* Verify that the given bytea contains a HASH page, or die in the attempt.
51-
* A pointer to the page is returned.
53+
* A pointer to a palloc'd, properly aligned copy of the page is returned.
5254
*/
5355
static Page
5456
verify_hash_page(bytea *raw_page, int flags)
5557
{
56-
Page page;
57-
int raw_page_size;
58+
Page page = get_page_from_raw(raw_page);
5859
int pagetype;
5960
HashPageOpaque pageopaque;
6061

61-
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
62-
63-
if (raw_page_size != BLCKSZ)
64-
ereport(ERROR,
65-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
66-
errmsg("invalid page size"),
67-
errdetail("Expected size %d, got %d",
68-
BLCKSZ, raw_page_size)));
69-
70-
page = VARDATA(raw_page);
71-
7262
if (PageIsNew(page))
7363
ereport(ERROR,
7464
(errcode(ERRCODE_INDEX_CORRUPTED),

contrib/pageinspect/heapfuncs.c

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
#include "postgres.h"
2727

28+
#include "pageinspect.h"
29+
2830
#include "access/htup_details.h"
2931
#include "funcapi.h"
3032
#include "catalog/pg_type.h"

contrib/pageinspect/pageinspect.h

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* pageinspect.h
4+
* Common functions for pageinspect.
5+
*
6+
* Copyright (c) 2017, PostgreSQL Global Development Group
7+
*
8+
* IDENTIFICATION
9+
* contrib/pageinspect/pageinspect.h
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
#ifndef _PAGEINSPECT_H_
14+
#define _PAGEINSPECT_H_
15+
16+
#include "storage/bufpage.h"
17+
18+
/* in rawpage.c */
19+
extern Page get_page_from_raw(bytea *raw_page);
20+
21+
#endif /* _PAGEINSPECT_H_ */

contrib/pageinspect/rawpage.c

+38
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "postgres.h"
1717

18+
#include "pageinspect.h"
19+
1820
#include "access/htup_details.h"
1921
#include "catalog/catalog.h"
2022
#include "catalog/namespace.h"
@@ -158,6 +160,42 @@ get_raw_page_internal(text *relname, ForkNumber forknum, BlockNumber blkno)
158160
return raw_page;
159161
}
160162

163+
164+
/*
165+
* get_page_from_raw
166+
*
167+
* Get a palloc'd, maxalign'ed page image from the result of get_raw_page()
168+
*
169+
* On machines with MAXALIGN = 8, the payload of a bytea is not maxaligned,
170+
* since it will start 4 bytes into a palloc'd value. On alignment-picky
171+
* machines, this will cause failures in accesses to 8-byte-wide values
172+
* within the page. We don't need to worry if accessing only 4-byte or
173+
* smaller fields, but when examining a struct that contains 8-byte fields,
174+
* use this function for safety.
175+
*/
176+
Page
177+
get_page_from_raw(bytea *raw_page)
178+
{
179+
Page page;
180+
int raw_page_size;
181+
182+
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
183+
184+
if (raw_page_size != BLCKSZ)
185+
ereport(ERROR,
186+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
187+
errmsg("invalid page size"),
188+
errdetail("Expected %d bytes, got %d.",
189+
BLCKSZ, raw_page_size)));
190+
191+
page = palloc(raw_page_size);
192+
193+
memcpy(page, VARDATA(raw_page), raw_page_size);
194+
195+
return page;
196+
}
197+
198+
161199
/*
162200
* page_header
163201
*

0 commit comments

Comments
 (0)