Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b66827c

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 e27453b commit b66827c

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

contrib/pageinspect/heapfuncs.c

+6-4
Original file line numberDiff line numberDiff line change
@@ -298,9 +298,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
298298
TupleDesc tupdesc;
299299

300300
/* Get tuple descriptor from relation OID */
301-
rel = relation_open(relid, NoLock);
302-
tupdesc = CreateTupleDescCopyConstr(rel->rd_att);
303-
relation_close(rel, NoLock);
301+
rel = relation_open(relid, AccessShareLock);
302+
tupdesc = RelationGetDescr(rel);
304303

305304
raw_attrs = initArrayResult(BYTEAOID, CurrentMemoryContext, false);
306305
nattrs = tupdesc->natts;
@@ -317,7 +316,6 @@ tuple_data_split_internal(Oid relid, char *tupdata,
317316
bytea *attr_data = NULL;
318317

319318
attr = TupleDescAttr(tupdesc, i);
320-
is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
321319

322320
/*
323321
* Tuple header can specify less attributes than tuple descriptor as
@@ -327,6 +325,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
327325
*/
328326
if (i >= (t_infomask2 & HEAP_NATTS_MASK))
329327
is_null = true;
328+
else
329+
is_null = (t_infomask & HEAP_HASNULL) && att_isnull(i, t_bits);
330330

331331
if (!is_null)
332332
{
@@ -386,6 +386,8 @@ tuple_data_split_internal(Oid relid, char *tupdata,
386386
(errcode(ERRCODE_DATA_CORRUPTED),
387387
errmsg("end of tuple reached without looking at all its data")));
388388

389+
relation_close(rel, AccessShareLock);
390+
389391
return makeArrayResult(raw_attrs, CurrentMemoryContext);
390392
}
391393

0 commit comments

Comments
 (0)