5
5
* contains the user-level large object application interface routines.
6
6
*
7
7
*
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
+ *
8
15
* Note: many of these routines leak memory in CurrentMemoryContext, as indeed
9
16
* does most of the backend code. We expect that CurrentMemoryContext will
10
17
* be a short-lived context. Data that must persist across function calls
17
24
*
18
25
*
19
26
* 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 $
21
28
*
22
29
*-------------------------------------------------------------------------
23
30
*/
@@ -330,8 +337,10 @@ inv_getsize(LargeObjectDesc *obj_desc)
330
337
bool pfreeit ;
331
338
332
339
found = true;
340
+ if (HeapTupleHasNulls (tuple )) /* paranoia */
341
+ elog (ERROR , "null field found in pg_largeobject" );
333
342
data = (Form_pg_largeobject ) GETSTRUCT (tuple );
334
- datafield = & (data -> data );
343
+ datafield = & (data -> data ); /* see note at top of file */
335
344
pfreeit = false;
336
345
if (VARATT_IS_EXTENDED (datafield ))
337
346
{
@@ -434,6 +443,8 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
434
443
bytea * datafield ;
435
444
bool pfreeit ;
436
445
446
+ if (HeapTupleHasNulls (tuple )) /* paranoia */
447
+ elog (ERROR , "null field found in pg_largeobject" );
437
448
data = (Form_pg_largeobject ) GETSTRUCT (tuple );
438
449
439
450
/*
@@ -457,7 +468,7 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
457
468
off = (int ) (obj_desc -> offset - pageoff );
458
469
Assert (off >= 0 && off < LOBLKSIZE );
459
470
460
- datafield = & (data -> data );
471
+ datafield = & (data -> data ); /* see note at top of file */
461
472
pfreeit = false;
462
473
if (VARATT_IS_EXTENDED (datafield ))
463
474
{
@@ -558,6 +569,8 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
558
569
{
559
570
if ((oldtuple = index_getnext (sd , ForwardScanDirection )) != NULL )
560
571
{
572
+ if (HeapTupleHasNulls (oldtuple )) /* paranoia */
573
+ elog (ERROR , "null field found in pg_largeobject" );
561
574
olddata = (Form_pg_largeobject ) GETSTRUCT (oldtuple );
562
575
Assert (olddata -> pageno >= pageno );
563
576
}
@@ -575,7 +588,7 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
575
588
*
576
589
* First, load old data into workbuf
577
590
*/
578
- datafield = & (olddata -> data );
591
+ datafield = & (olddata -> data ); /* see note at top of file */
579
592
pfreeit = false;
580
593
if (VARATT_IS_EXTENDED (datafield ))
581
594
{
@@ -737,6 +750,8 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
737
750
olddata = NULL ;
738
751
if ((oldtuple = index_getnext (sd , ForwardScanDirection )) != NULL )
739
752
{
753
+ if (HeapTupleHasNulls (oldtuple )) /* paranoia */
754
+ elog (ERROR , "null field found in pg_largeobject" );
740
755
olddata = (Form_pg_largeobject ) GETSTRUCT (oldtuple );
741
756
Assert (olddata -> pageno >= pageno );
742
757
}
@@ -749,7 +764,7 @@ inv_truncate(LargeObjectDesc *obj_desc, int len)
749
764
if (olddata != NULL && olddata -> pageno == pageno )
750
765
{
751
766
/* First, load old data into workbuf */
752
- bytea * datafield = & (olddata -> data );
767
+ bytea * datafield = & (olddata -> data ); /* see note at top of file */
753
768
bool pfreeit = false;
754
769
int pagelen ;
755
770
0 commit comments