Skip to content

Commit ec5f71a

Browse files
committed
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
1 parent 0360c53 commit ec5f71a

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

contrib/pageinspect/heapfuncs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
296296
TupleDesc tupdesc;
297297

298298
/* Get tuple descriptor from relation OID */
299-
rel = relation_open(relid, NoLock);
300-
tupdesc = CreateTupleDescCopyConstr(rel->rd_att);
301-
relation_close(rel, NoLock);
299+
rel = relation_open(relid, AccessShareLock);
300+
tupdesc = RelationGetDescr(rel);
302301

303302
raw_attrs = initArrayResult(BYTEAOID, CurrentMemoryContext, false);
304303
nattrs = tupdesc->natts;
@@ -315,7 +314,6 @@ tuple_data_split_internal(Oid relid, char *tupdata,
315314
bytea *attr_data = NULL;
316315

317316
attr = tupdesc->attrs[i];
318-
is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
319317

320318
/*
321319
* Tuple header can specify less attributes than tuple descriptor as
@@ -325,6 +323,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
325323
*/
326324
if (i >= (t_infomask2 & HEAP_NATTS_MASK))
327325
is_null = true;
326+
else
327+
is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
328328

329329
if (!is_null)
330330
{
@@ -384,6 +384,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
384384
(errcode(ERRCODE_DATA_CORRUPTED),
385385
errmsg("end of tuple reached without looking at all its data")));
386386

387+
relation_close(rel, AccessShareLock);
388+
387389
return makeArrayResult(raw_attrs, CurrentMemoryContext);
388390
}
389391

0 commit comments

Comments
 (0)