@ -30,6 +30,9 @@ PG_FUNCTION_INFO_V1(verify_heapam);
/* The number of columns in tuples returned by verify_heapam */
# define HEAPCHECK_RELATION_COLS 4
/* The largest valid toast va_rawsize */
# define VARLENA_SIZE_LIMIT 0x3FFFFFFF
/*
* Despite the name , we use this for reporting problems with both XIDs and
* MXIDs .
@ -1414,6 +1417,49 @@ check_tuple_attribute(HeapCheckContext *ctx)
*/
VARATT_EXTERNAL_GET_POINTER ( toast_pointer , attr ) ;
/* Toasted attributes too large to be untoasted should never be stored */
if ( toast_pointer . va_rawsize > VARLENA_SIZE_LIMIT )
report_corruption ( ctx ,
psprintf ( " toast value %u rawsize %u exceeds limit %u " ,
toast_pointer . va_valueid ,
toast_pointer . va_rawsize ,
VARLENA_SIZE_LIMIT ) ) ;
if ( VARATT_IS_COMPRESSED ( & toast_pointer ) )
{
ToastCompressionId cmid ;
bool valid = false ;
/* Compression should never expand the attribute */
if ( VARATT_EXTERNAL_GET_EXTSIZE ( toast_pointer ) > toast_pointer . va_rawsize - VARHDRSZ )
report_corruption ( ctx ,
psprintf ( " toast value %u external size %u exceeds maximum expected for rawsize %u " ,
toast_pointer . va_valueid ,
VARATT_EXTERNAL_GET_EXTSIZE ( toast_pointer ) ,
toast_pointer . va_rawsize ) ) ;
/* Compressed attributes should have a valid compression method */
cmid = TOAST_COMPRESS_METHOD ( & toast_pointer ) ;
switch ( cmid )
{
/* List of all valid compression method IDs */
case TOAST_PGLZ_COMPRESSION_ID :
case TOAST_LZ4_COMPRESSION_ID :
valid = true ;
break ;
/* Recognized but invalid compression method ID */
case TOAST_INVALID_COMPRESSION_ID :
break ;
/* Intentionally no default here */
}
if ( ! valid )
report_corruption ( ctx ,
psprintf ( " toast value %u has invalid compression method id %d " ,
toast_pointer . va_valueid , cmid ) ) ;
}
/* The tuple header better claim to contain toasted values */
if ( ! ( infomask & HEAP_HASEXTERNAL ) )
{