mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04: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_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, | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user