1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

Fix lo_read, lo_write, lo_truncate to cope with "size_t" length parameters.

libpq defines these functions as accepting "size_t" lengths ... but the
underlying backend functions expect signed int32 length parameters, and so
will misinterpret any value exceeding INT_MAX.  Fix the libpq side to throw
error rather than possibly doing something unexpected.

This is a bug of long standing, but I doubt it's worth back-patching.  The
problem is really pretty academic anyway with lo_read/lo_write, since any
caller expecting sane behavior would have to have provided a multi-gigabyte
buffer.  It's slightly more pressing with lo_truncate, but still we haven't
supported large objects over 2GB until now.
This commit is contained in:
Tom Lane
2012-10-08 21:12:27 -04:00
parent b6d4522296
commit 0e924c007d
2 changed files with 90 additions and 16 deletions

View File

@ -31,6 +31,7 @@
#endif
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <netinet/in.h> /* for ntohl/htonl */
#include <arpa/inet.h>
@ -155,13 +156,29 @@ lo_truncate(PGconn *conn, int fd, size_t len)
return -1;
}
/*
* Long ago, somebody thought it'd be a good idea to declare this function
* as taking size_t ... but the underlying backend function only accepts a
* signed int32 length. So throw error if the given value overflows
* int32. (A possible alternative is to automatically redirect the call
* to lo_truncate64; but if the caller wanted to rely on that backend
* function being available, he could have called lo_truncate64 for
* himself.)
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
return -1;
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
argv[1].isint = 1;
argv[1].len = 4;
argv[1].u.integer = len;
argv[1].u.integer = (int) len;
res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate,
&retval, &result_len, 1, argv, 2);
@ -251,13 +268,26 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
return -1;
}
/*
* Long ago, somebody thought it'd be a good idea to declare this function
* as taking size_t ... but the underlying backend function only accepts a
* signed int32 length. So throw error if the given value overflows
* int32.
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_read exceeds integer range\n"));
return -1;
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
argv[1].isint = 1;
argv[1].len = 4;
argv[1].u.integer = len;
argv[1].u.integer = (int) len;
res = PQfn(conn, conn->lobjfuncs->fn_lo_read,
(int *) buf, &result_len, 0, argv, 2);
@ -293,15 +323,25 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
return -1;
}
if (len <= 0)
return 0;
/*
* Long ago, somebody thought it'd be a good idea to declare this function
* as taking size_t ... but the underlying backend function only accepts a
* signed int32 length. So throw error if the given value overflows
* int32.
*/
if (len > (size_t) INT_MAX)
{
printfPQExpBuffer(&conn->errorMessage,
libpq_gettext("argument of lo_write exceeds integer range\n"));
return -1;
}
argv[0].isint = 1;
argv[0].len = 4;
argv[0].u.integer = fd;
argv[1].isint = 0;
argv[1].len = len;
argv[1].len = (int) len;
argv[1].u.ptr = (int *) buf;
res = PQfn(conn, conn->lobjfuncs->fn_lo_write,