]> granicus.if.org Git - postgresql/commitdiff
Add some simple defenses against null fields in pg_largeobject, and add
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 12 Jun 2007 19:46:24 +0000 (19:46 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 12 Jun 2007 19:46:24 +0000 (19:46 +0000)
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.

src/backend/storage/large_object/inv_api.c

index ea98ab2952069a6224e375a15e5e0e596ae30386..77b756cabb99339b2500c5311f1bee33dc5f081c 100644 (file)
@@ -5,6 +5,13 @@
  *       contains the user-level large object application interface routines.
  *
  *
+ * Note: we access pg_largeobject.data using its C struct declaration.
+ * This is safe because it immediately follows pageno which is an int4 field,
+ * and therefore the data field will always be 4-byte aligned, even if it
+ * is in the short 1-byte-header format.  We have to detoast it since it's
+ * quite likely to be in compressed or short format.  We also need to check
+ * for NULLs, since initdb will mark loid and pageno but not data as NOT NULL.
+ *
  * Note: many of these routines leak memory in CurrentMemoryContext, as indeed
  * does most of the backend code.  We expect that CurrentMemoryContext will
  * be a short-lived context.  Data that must persist across function calls
@@ -17,7 +24,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.124 2007/04/06 04:21:42 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.125 2007/06/12 19:46:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -330,8 +337,10 @@ inv_getsize(LargeObjectDesc *obj_desc)
                bool            pfreeit;
 
                found = true;
+               if (HeapTupleHasNulls(tuple))                           /* paranoia */
+                       elog(ERROR, "null field found in pg_largeobject");
                data = (Form_pg_largeobject) GETSTRUCT(tuple);
-               datafield = &(data->data);
+               datafield = &(data->data);                      /* see note at top of file */
                pfreeit = false;
                if (VARATT_IS_EXTENDED(datafield))
                {
@@ -434,6 +443,8 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
                bytea      *datafield;
                bool            pfreeit;
 
+               if (HeapTupleHasNulls(tuple))                           /* paranoia */
+                       elog(ERROR, "null field found in pg_largeobject");
                data = (Form_pg_largeobject) GETSTRUCT(tuple);
 
                /*
@@ -457,7 +468,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
                        off = (int) (obj_desc->offset - pageoff);
                        Assert(off >= 0 && off < LOBLKSIZE);
 
-                       datafield = &(data->data);
+                       datafield = &(data->data);                      /* see note at top of file */
                        pfreeit = false;
                        if (VARATT_IS_EXTENDED(datafield))
                        {
@@ -558,6 +569,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
                {
                        if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)
                        {
+                               if (HeapTupleHasNulls(oldtuple))                        /* paranoia */
+                                       elog(ERROR, "null field found in pg_largeobject");
                                olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);
                                Assert(olddata->pageno >= pageno);
                        }
@@ -575,7 +588,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
                         *
                         * First, load old data into workbuf
                         */
-                       datafield = &(olddata->data);
+                       datafield = &(olddata->data);           /* see note at top of file */
                        pfreeit = false;
                        if (VARATT_IS_EXTENDED(datafield))
                        {
@@ -737,6 +750,8 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
        olddata = NULL;
        if ((oldtuple = index_getnext(sd, ForwardScanDirection)) != NULL)
        {
+               if (HeapTupleHasNulls(oldtuple))                                /* paranoia */
+                       elog(ERROR, "null field found in pg_largeobject");
                olddata = (Form_pg_largeobject) GETSTRUCT(oldtuple);
                Assert(olddata->pageno >= pageno);
        }
@@ -749,7 +764,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
        if (olddata != NULL && olddata->pageno == pageno)
        {
                /* First, load old data into workbuf */
-               bytea *datafield = &(olddata->data);
+               bytea *datafield = &(olddata->data);    /* see note at top of file */
                bool pfreeit = false;
                int pagelen;