summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2018-10-01 15:51:07 +0000
committerTom Lane2018-10-01 15:51:07 +0000
commitec5f71aeadf977399707a54e4798aedc963c85e7 (patch)
tree163da3cb90a1603e9ff733b9eedadc4e928d324b
parent0360c539f2a2a979a98b9bb4ae4b3d8b77ee199b (diff)
Fix tuple_data_split() to not open a relation without any lock.
contrib/pageinspect's tuple_data_split() function thought it could get away with opening the referenced relation with NoLock. In practice there's no guarantee that the current session holds any lock on that rel (even if we just read a page from it), so that this is unsafe. Switch to using AccessShareLock. Also, postpone closing the relation, so that we needn't copy its tupdesc. Also, fix unsafe use of att_isnull() for attributes past the end of the tuple. Per testing with a patch that complains if we open a relation without holding any lock on it. I don't plan to back-patch that patch, but we should close the holes it identifies in all supported branches. Discussion: https://postgr.es/m/2038.1538335244@sss.pgh.pa.us
-rw-r--r--contrib/pageinspect/heapfuncs.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/contrib/pageinspect/heapfuncs.c b/contrib/pageinspect/heapfuncs.c
index 76d2cd1d278..53162975e9d 100644
--- a/contrib/pageinspect/heapfuncs.c
+++ b/contrib/pageinspect/heapfuncs.c
@@ -296,9 +296,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
TupleDesc tupdesc;
/* Get tuple descriptor from relation OID */
- rel = relation_open(relid, NoLock);
- tupdesc = CreateTupleDescCopyConstr(rel->rd_att);
- relation_close(rel, NoLock);
+ rel = relation_open(relid, AccessShareLock);
+ tupdesc = RelationGetDescr(rel);
raw_attrs = initArrayResult(BYTEAOID, CurrentMemoryContext, false);
nattrs = tupdesc->natts;
@@ -315,7 +314,6 @@ tuple_data_split_internal(Oid relid, char *tupdata,
bytea *attr_data = NULL;
attr = tupdesc->attrs[i];
- is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
/*
* Tuple header can specify less attributes than tuple descriptor as
@@ -325,6 +323,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
*/
if (i >= (t_infomask2 & HEAP_NATTS_MASK))
is_null = true;
+ else
+ is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
if (!is_null)
{
@@ -384,6 +384,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
(errcode(ERRCODE_DATA_CORRUPTED),
errmsg("end of tuple reached without looking at all its data")));
+ relation_close(rel, AccessShareLock);
+
return makeArrayResult(raw_attrs, CurrentMemoryContext);
}