mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-30 19:00:29 +08:00
pageinspect: Fix unaligned struct access in GIN functions
The raw page data that is passed into the functions will not be aligned at 8-byte boundaries. Casting that to a struct and accessing int64 fields will result in unaligned access. On most platforms, you get away with it, but it will result on a crash on pickier platforms such as ia64 and sparc64.
This commit is contained in:
parent
f2e6a2ccf1
commit
84ad68d645
@ -28,11 +28,31 @@ PG_FUNCTION_INFO_V1(gin_metapage_info);
|
|||||||
PG_FUNCTION_INFO_V1(gin_page_opaque_info);
|
PG_FUNCTION_INFO_V1(gin_page_opaque_info);
|
||||||
PG_FUNCTION_INFO_V1(gin_leafpage_items);
|
PG_FUNCTION_INFO_V1(gin_leafpage_items);
|
||||||
|
|
||||||
|
|
||||||
|
static Page
|
||||||
|
get_page_from_raw(bytea *raw_page)
|
||||||
|
{
|
||||||
|
int raw_page_size;
|
||||||
|
Page page;
|
||||||
|
|
||||||
|
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
|
||||||
|
if (raw_page_size < BLCKSZ)
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||||
|
errmsg("input page too small (%d bytes)", raw_page_size)));
|
||||||
|
|
||||||
|
/* make a copy so that the page is properly aligned for struct access */
|
||||||
|
page = palloc(raw_page_size);
|
||||||
|
memcpy(page, VARDATA(raw_page), raw_page_size);
|
||||||
|
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
gin_metapage_info(PG_FUNCTION_ARGS)
|
gin_metapage_info(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
||||||
int raw_page_size;
|
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
Page page;
|
Page page;
|
||||||
GinPageOpaque opaq;
|
GinPageOpaque opaq;
|
||||||
@ -46,12 +66,7 @@ gin_metapage_info(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
(errmsg("must be superuser to use raw page functions"))));
|
(errmsg("must be superuser to use raw page functions"))));
|
||||||
|
|
||||||
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
|
page = get_page_from_raw(raw_page);
|
||||||
if (raw_page_size < BLCKSZ)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("input page too small (%d bytes)", raw_page_size)));
|
|
||||||
page = VARDATA(raw_page);
|
|
||||||
|
|
||||||
opaq = (GinPageOpaque) PageGetSpecialPointer(page);
|
opaq = (GinPageOpaque) PageGetSpecialPointer(page);
|
||||||
if (opaq->flags != GIN_META)
|
if (opaq->flags != GIN_META)
|
||||||
@ -94,7 +109,6 @@ Datum
|
|||||||
gin_page_opaque_info(PG_FUNCTION_ARGS)
|
gin_page_opaque_info(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
||||||
int raw_page_size;
|
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
Page page;
|
Page page;
|
||||||
GinPageOpaque opaq;
|
GinPageOpaque opaq;
|
||||||
@ -110,12 +124,7 @@ gin_page_opaque_info(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
(errmsg("must be superuser to use raw page functions"))));
|
(errmsg("must be superuser to use raw page functions"))));
|
||||||
|
|
||||||
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
|
page = get_page_from_raw(raw_page);
|
||||||
if (raw_page_size < BLCKSZ)
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("input page too small (%d bytes)", raw_page_size)));
|
|
||||||
page = VARDATA(raw_page);
|
|
||||||
|
|
||||||
opaq = (GinPageOpaque) PageGetSpecialPointer(page);
|
opaq = (GinPageOpaque) PageGetSpecialPointer(page);
|
||||||
|
|
||||||
@ -173,7 +182,6 @@ Datum
|
|||||||
gin_leafpage_items(PG_FUNCTION_ARGS)
|
gin_leafpage_items(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
||||||
int raw_page_size;
|
|
||||||
FuncCallContext *fctx;
|
FuncCallContext *fctx;
|
||||||
gin_leafpage_items_state *inter_call_data;
|
gin_leafpage_items_state *inter_call_data;
|
||||||
|
|
||||||
@ -182,8 +190,6 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
|
|||||||
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
(errmsg("must be superuser to use raw page functions"))));
|
(errmsg("must be superuser to use raw page functions"))));
|
||||||
|
|
||||||
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
|
|
||||||
|
|
||||||
if (SRF_IS_FIRSTCALL())
|
if (SRF_IS_FIRSTCALL())
|
||||||
{
|
{
|
||||||
TupleDesc tupdesc;
|
TupleDesc tupdesc;
|
||||||
@ -191,11 +197,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS)
|
|||||||
Page page;
|
Page page;
|
||||||
GinPageOpaque opaq;
|
GinPageOpaque opaq;
|
||||||
|
|
||||||
if (raw_page_size < BLCKSZ)
|
page = get_page_from_raw(raw_page);
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
||||||
errmsg("input page too small (%d bytes)", raw_page_size)));
|
|
||||||
page = VARDATA(raw_page);
|
|
||||||
|
|
||||||
if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
|
if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData)))
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
|
Loading…
Reference in New Issue
Block a user