From: Peter Eisentraut Date: Fri, 4 Nov 2016 16:00:00 +0000 (-0400) Subject: pageinspect: Fix unaligned struct access in GIN functions X-Git-Tag: REL_10_BETA1~1463 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=84ad68d645222f534e4fe51fbba43a5c9cc382a5;p=postgresql 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. --- diff --git a/contrib/pageinspect/ginfuncs.c b/contrib/pageinspect/ginfuncs.c index 145e2ce709..6e4103df6a 100644 --- a/contrib/pageinspect/ginfuncs.c +++ b/contrib/pageinspect/ginfuncs.c @@ -28,11 +28,31 @@ PG_FUNCTION_INFO_V1(gin_metapage_info); PG_FUNCTION_INFO_V1(gin_page_opaque_info); 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 gin_metapage_info(PG_FUNCTION_ARGS) { bytea *raw_page = PG_GETARG_BYTEA_P(0); - int raw_page_size; TupleDesc tupdesc; Page page; GinPageOpaque opaq; @@ -46,12 +66,7 @@ gin_metapage_info(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); - 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))); - page = VARDATA(raw_page); + page = get_page_from_raw(raw_page); opaq = (GinPageOpaque) PageGetSpecialPointer(page); if (opaq->flags != GIN_META) @@ -94,7 +109,6 @@ Datum gin_page_opaque_info(PG_FUNCTION_ARGS) { bytea *raw_page = PG_GETARG_BYTEA_P(0); - int raw_page_size; TupleDesc tupdesc; Page page; GinPageOpaque opaq; @@ -110,12 +124,7 @@ gin_page_opaque_info(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); - 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))); - page = VARDATA(raw_page); + page = get_page_from_raw(raw_page); opaq = (GinPageOpaque) PageGetSpecialPointer(page); @@ -173,7 +182,6 @@ Datum gin_leafpage_items(PG_FUNCTION_ARGS) { bytea *raw_page = PG_GETARG_BYTEA_P(0); - int raw_page_size; FuncCallContext *fctx; gin_leafpage_items_state *inter_call_data; @@ -182,8 +190,6 @@ gin_leafpage_items(PG_FUNCTION_ARGS) (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw page functions")))); - raw_page_size = VARSIZE(raw_page) - VARHDRSZ; - if (SRF_IS_FIRSTCALL()) { TupleDesc tupdesc; @@ -191,11 +197,7 @@ gin_leafpage_items(PG_FUNCTION_ARGS) Page page; GinPageOpaque opaq; - 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); + page = get_page_from_raw(raw_page); if (PageGetSpecialSize(page) != MAXALIGN(sizeof(GinPageOpaqueData))) ereport(ERROR,