Since pg11 pg_read_file() and friends can be used with absolute paths as long as
the user is superuser or explicitly granted the role pg_read_server_files.

I noticed that when trying to read a virtual file, e.g.:

  SELECT pg_read_file('/proc/self/status');

the returned result is a zero length string.

However this works fine:

  SELECT pg_read_file('/proc/self/status', 127, 128);

The reason for that is pg_read_file_v2() sets bytes_to_read=-1 if no offset and
length are supplied as arguments when it is called. It passes bytes_to_read down
to read_binary_file().

When the latter function sees bytes_to_read < 0 it tries to read the entire file
by getting the file size via stat, which returns 0 for a virtual file size.

The attached patch fixes this for me. I think it ought to be backpatched through
pg11.

Comments?

Joe
-- 
Crunchy Data - http://crunchydata.com
PostgreSQL Support for Secure Enterprises
Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/adt/genfile.c b/src/backend/utils/adt/genfile.c
index ceaa618..101df3a 100644
*** a/src/backend/utils/adt/genfile.c
--- b/src/backend/utils/adt/genfile.c
***************
*** 36,41 ****
--- 36,42 ----
  #include "utils/syscache.h"
  #include "utils/timestamp.h"
  
+ #define READBUF_SIZE	4096
  
  /*
   * Convert a "text" filename argument to C string, and check it's allowable.
*************** read_binary_file(const char *filename, i
*** 106,112 ****
  				 bool missing_ok)
  {
  	bytea	   *buf;
! 	size_t		nbytes;
  	FILE	   *file;
  
  	if (bytes_to_read < 0)
--- 107,113 ----
  				 bool missing_ok)
  {
  	bytea	   *buf;
! 	size_t		nbytes = 0;
  	FILE	   *file;
  
  	if (bytes_to_read < 0)
*************** read_binary_file(const char *filename, i
*** 154,162 ****
  				(errcode_for_file_access(),
  				 errmsg("could not seek in file \"%s\": %m", filename)));
  
! 	buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
  
! 	nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
  
  	if (ferror(file))
  		ereport(ERROR,
--- 155,187 ----
  				(errcode_for_file_access(),
  				 errmsg("could not seek in file \"%s\": %m", filename)));
  
! 	if (bytes_to_read > 0)
! 	{
! 		buf = (bytea *) palloc((Size) bytes_to_read + VARHDRSZ);
  
! 		nbytes = fread(VARDATA(buf), 1, (size_t) bytes_to_read, file);
! 	}
! 	else
! 	{
! 		/* bytes_to_read can be <= zero if the file is a virtual file */
! 		StringInfoData	sbuf;
! 		size_t			rbytes = 0;
! 		char			rbuf[READBUF_SIZE];
! 
! 		initStringInfo(&sbuf);
! 		while (!feof(file))
! 		{
! 			memset(rbuf, '\0', READBUF_SIZE);
! 			rbytes = fread(rbuf, 1, (size_t) READBUF_SIZE, file);
! 			nbytes += rbytes;
! 
! 			appendStringInfoString(&sbuf, rbuf);
! 		}
! 
! 		Assert(nbytes == sbuf.len);
! 		buf = (bytea *) palloc((Size) nbytes + VARHDRSZ);
! 		memcpy(VARDATA(buf), sbuf.data, nbytes);
! 	}
  
  	if (ferror(file))
  		ereport(ERROR,

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to