diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2012-01-27 20:08:34 +0200 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2012-01-27 20:08:34 +0200 |
commit | 8a3f745f160d8334ad978676828d3926ac949f43 (patch) | |
tree | cccdd60563e196b388dab9b915f25f7548a11614 /src/backend/utils/cache/relcache.c | |
parent | eb6af016fc04392c41106ac866072914bf66ecd0 (diff) | |
download | postgresql-8a3f745f160d8334ad978676828d3926ac949f43.tar.gz postgresql-8a3f745f160d8334ad978676828d3926ac949f43.zip |
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
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index d0138fc7e84..a59950e45a0 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -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; } |