Do not access indclass through Form_pg_index

Normally, accessing variable-length members of catalog structures past
the first one doesn't work at all.  Here, it happened to work because
indnatts was checked to be 1, and so the defined FormData_pg_index
layout, using int2vector[1] and oidvector[1] for variable-length
arrays, happened to match the actual memory layout.  But it's a very
fragile assumption, and it's not in a performance-critical path, so
code it properly using heap_getattr() instead.

bug analysis by Tom Lane
This commit is contained in:
Peter Eisentraut 2012-01-27 20:08:34 +02:00
parent eb6af016fc
commit 8a3f745f16

View File

@ -3351,15 +3351,30 @@ RelationGetIndexList(Relation relation)
while (HeapTupleIsValid(htup = systable_getnext(indscan)))
{
Form_pg_index index = (Form_pg_index) GETSTRUCT(htup);
Datum indclassDatum;
oidvector *indclass;
bool isnull;
/* Add index's OID to result list in the proper order */
result = insert_ordered_oid(result, index->indexrelid);
/*
* indclass cannot be referenced directly through the C struct, because
* it comes after the variable-width indkey field. Must extract the
* datum the hard way...
*/
indclassDatum = heap_getattr(htup,
Anum_pg_index_indclass,
GetPgIndexDescriptor(),
&isnull);
Assert(!isnull);
indclass = (oidvector *) DatumGetPointer(indclassDatum);
/* Check to see if it is a unique, non-partial btree index on OID */
if (index->indnatts == 1 &&
index->indisunique && index->indimmediate &&
index->indkey.values[0] == ObjectIdAttributeNumber &&
index->indclass.values[0] == OID_BTREE_OPS_OID &&
indclass->values[0] == OID_BTREE_OPS_OID &&
heap_attisnull(htup, Anum_pg_index_indpred))
oidIndex = index->indexrelid;
}