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

Commit e976fd4

Browse files
committed
Add some simple defenses against null fields in pg_largeobject, and add
comments noting that there's an alignment assumption now that the data field could be in 1-byte-header format. Per discussion with Greg Stark.
1 parent ee0d34a commit e976fd4

File tree

1 file changed

+20
-5
lines changed

1 file changed

+20
-5
lines changed

src/backend/storage/large_object/inv_api.c

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
* contains the user-level large object application interface routines.
66
*
77
*
8+
* Note: we access pg_largeobject.data using its C struct declaration.
9+
* This is safe because it immediately follows pageno which is an int4 field,
10+
* and therefore the data field will always be 4-byte aligned, even if it
11+
* is in the short 1-byte-header format. We have to detoast it since it's
12+
* quite likely to be in compressed or short format. We also need to check
13+
* for NULLs, since initdb will mark loid and pageno but not data as NOT NULL.
14+
*
815
* Note: many of these routines leak memory in CurrentMemoryContext, as indeed
916
* does most of the backend code. We expect that CurrentMemoryContext will
1017
* be a short-lived context. Data that must persist across function calls
@@ -17,7 +24,7 @@
1724
*
1825
*
1926
* IDENTIFICATION
20-
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.124 2007/04/06 04:21:42 tgl Exp $
27+
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.125 2007/06/12 19:46:24 tgl Exp $
2128
*
2229
*-------------------------------------------------------------------------
2330
*/
@@ -330,8 +337,10 @@ inv_getsize(LargeObjectDesc *obj_desc)
330337
bool pfreeit;
331338

332339
found = true;
340+
if (HeapTupleHasNulls(tuple)) /* paranoia */
341+
elog(ERROR, "null field found in pg_largeobject");
333342
data = (Form_pg_largeobject) GETSTRUCT(tuple);
334-
datafield = &(data->data);
343+
datafield = &(data->data); /* see note at top of file */
335344
pfreeit = false;
336345
if (VARATT_IS_EXTENDED(datafield))
337346
{
@@ -434,6 +443,8 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
434443
bytea *datafield;
435444
bool pfreeit;
436445

446+
if (HeapTupleHasNulls(tuple)) /* paranoia */
447+
elog(ERROR, "null field found in pg_largeobject");
437448
data = (Form_pg_largeobject) GETSTRUCT(tuple);
438449

439450
/*
@@ -457,7 +468,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
457468
off = (int) (obj_desc->offset - pageoff);
458469
Assert(off >= 0 && off < LOBLKSIZE);
459470

460-
datafield = &(data->data);
471+
datafield = &(data->data); /* see note at top of file */
461472
pfreeit = false;
462473
if (VARATT_IS_EXTENDED(datafield))
463474
{
@@ -558,6 +569,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
558569
{
559570
if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)
560571
{
572+
if (HeapTupleHasNulls(oldtuple)) /* paranoia */
573+
elog(ERROR, "null field found in pg_largeobject");
561574
olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);
562575
Assert(olddata->pageno >= pageno);
563576
}
@@ -575,7 +588,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
575588
*
576589
* First, load old data into workbuf
577590
*/
578-
datafield = &(olddata->data);
591+
datafield = &(olddata->data); /* see note at top of file */
579592
pfreeit = false;
580593
if (VARATT_IS_EXTENDED(datafield))
581594
{
@@ -737,6 +750,8 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
737750
olddata = NULL;
738751
if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)
739752
{
753+
if (HeapTupleHasNulls(oldtuple)) /* paranoia */
754+
elog(ERROR, "null field found in pg_largeobject");
740755
olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);
741756
Assert(olddata->pageno >= pageno);
742757
}
@@ -749,7 +764,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
749764
if (olddata != NULL && olddata->pageno == pageno)
750765
{
751766
/* First, load old data into workbuf */
752-
bytea *datafield = &(olddata->data);
767+
bytea *datafield = &(olddata->data); /* see note at top of file */
753768
bool pfreeit = false;
754769
int pagelen;
755770

0 commit comments

Comments
 (0)