summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane2012-10-08 22:24:06 +0000
committerTom Lane2012-10-08 22:24:32 +0000
commit26fe56481c0f7baa705f0b3265b5a0676f894a94 (patch)
tree60bfe35565e16c168915e10500f3b61440f7865f /src/backend
parent878daf2e72755feadbfb8d21aad26dafd8658086 (diff)
Code review for 64-bit-large-object patch.
Fix broken-on-bigendian-machines byte-swapping functions, add missed update of alternate regression expected file, improve error reporting, remove some unnecessary code, sync testlo64.c with current testlo.c (it seems to have been cloned from a very old copy of that), assorted cosmetic improvements.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/libpq/be-fsstubs.c60
-rw-r--r--src/backend/storage/large_object/inv_api.c75
-rw-r--r--src/backend/utils/errcodes.txt1
3 files changed, 73 insertions, 63 deletions
diff --git a/src/backend/libpq/be-fsstubs.c b/src/backend/libpq/be-fsstubs.c
index 4bc81ba9f4d..c4ac1a650f5 100644
--- a/src/backend/libpq/be-fsstubs.c
+++ b/src/backend/libpq/be-fsstubs.c
@@ -39,7 +39,6 @@
#include "postgres.h"
#include <fcntl.h>
-#include <limits.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -57,7 +56,9 @@
*/
bool lo_compat_privileges;
-/*#define FSDB 1*/
+/* define this to enable debug logging */
+/* #define FSDB 1 */
+/* chunk size for lo_import/lo_export transfers */
#define BUFSIZE 8192
/*
@@ -210,7 +211,6 @@ lo_write(int fd, const char *buf, int len)
return status;
}
-
Datum
lo_lseek(PG_FUNCTION_ARGS)
{
@@ -226,42 +226,31 @@ lo_lseek(PG_FUNCTION_ARGS)
status = inv_seek(cookies[fd], offset, whence);
- if (INT_MAX < status)
- {
+ /* guard against result overflow */
+ if (status != (int32) status)
ereport(ERROR,
- (errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
- errmsg("offset overflow: %d", fd)));
- PG_RETURN_INT32(-1);
- }
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("lo_lseek result out of range for large-object descriptor %d",
+ fd)));
- PG_RETURN_INT32(status);
+ PG_RETURN_INT32((int32) status);
}
-
Datum
lo_lseek64(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
int64 offset = PG_GETARG_INT64(1);
int32 whence = PG_GETARG_INT32(2);
- MemoryContext currentContext;
- int64 status;
+ int64 status;
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
- {
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("invalid large-object descriptor: %d", fd)));
- PG_RETURN_INT64(-1);
- }
-
- Assert(fscxt != NULL);
- currentContext = MemoryContextSwitchTo(fscxt);
status = inv_seek(cookies[fd], offset, whence);
- MemoryContextSwitchTo(currentContext);
-
PG_RETURN_INT64(status);
}
@@ -301,7 +290,7 @@ Datum
lo_tell(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
- int64 offset = 0;
+ int64 offset;
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
ereport(ERROR,
@@ -310,37 +299,30 @@ lo_tell(PG_FUNCTION_ARGS)
offset = inv_tell(cookies[fd]);
- if (INT_MAX < offset)
- {
+ /* guard against result overflow */
+ if (offset != (int32) offset)
ereport(ERROR,
- (errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
- errmsg("offset overflow: %d", fd)));
- PG_RETURN_INT32(-1);
- }
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("lo_tell result out of range for large-object descriptor %d",
+ fd)));
- PG_RETURN_INT32(offset);
+ PG_RETURN_INT32((int32) offset);
}
-
Datum
lo_tell64(PG_FUNCTION_ARGS)
{
int32 fd = PG_GETARG_INT32(0);
+ int64 offset;
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
- {
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("invalid large-object descriptor: %d", fd)));
- PG_RETURN_INT64(-1);
- }
- /*
- * We assume we do not need to switch contexts for inv_tell. That is
- * true for now, but is probably more than this module ought to
- * assume...
- */
- PG_RETURN_INT64(inv_tell(cookies[fd]));
+ offset = inv_tell(cookies[fd]);
+
+ PG_RETURN_INT64(offset);
}
Datum
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index 3f5688b939b..5dd17823c23 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -30,6 +30,8 @@
*/
#include "postgres.h"
+#include <limits.h>
+
#include "access/genam.h"
#include "access/heapam.h"
#include "access/sysattr.h"
@@ -264,7 +266,10 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt)
retval->flags = IFS_RDLOCK;
}
else
- elog(ERROR, "invalid flags: %d", flags);
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid flags for opening a large object: %d",
+ flags)));
/* Can't use LargeObjectExists here because it always uses SnapshotNow */
if (!myLargeObjectExists(lobjId, retval->snapshot))
@@ -381,34 +386,45 @@ inv_getsize(LargeObjectDesc *obj_desc)
int64
inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence)
{
+ int64 newoffset;
+
Assert(PointerIsValid(obj_desc));
+ /*
+ * Note: overflow in the additions is possible, but since we will reject
+ * negative results, we don't need any extra test for that.
+ */
switch (whence)
{
case SEEK_SET:
- if (offset < 0 || offset >= MAX_LARGE_OBJECT_SIZE)
- elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
- obj_desc->offset = offset;
+ newoffset = offset;
break;
case SEEK_CUR:
- if ((offset + obj_desc->offset) < 0 ||
- (offset + obj_desc->offset) >= MAX_LARGE_OBJECT_SIZE)
- elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
- obj_desc->offset += offset;
+ newoffset = obj_desc->offset + offset;
break;
case SEEK_END:
- {
- int64 pos = inv_getsize(obj_desc) + offset;
-
- if (pos < 0 || pos >= MAX_LARGE_OBJECT_SIZE)
- elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
- obj_desc->offset = pos;
- }
+ newoffset = inv_getsize(obj_desc) + offset;
break;
default:
- elog(ERROR, "invalid whence: %d", whence);
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid whence setting: %d", whence)));
+ newoffset = 0; /* keep compiler quiet */
+ break;
}
- return obj_desc->offset;
+
+ /*
+ * use errmsg_internal here because we don't want to expose INT64_FORMAT
+ * in translatable strings; doing better is not worth the trouble
+ */
+ if (newoffset < 0 || newoffset > MAX_LARGE_OBJECT_SIZE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg_internal("invalid large object seek target: " INT64_FORMAT,
+ newoffset)));
+
+ obj_desc->offset = newoffset;
+ return newoffset;
}
int64
@@ -438,9 +454,6 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
if (nbytes <= 0)
return 0;
- if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
- elog(ERROR, "invalid read request size: %d", nbytes);
-
open_lo_relation();
ScanKeyInit(&skey[0],
@@ -559,13 +572,18 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
if (!LargeObjectExists(obj_desc->id))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("large object %u was already dropped", obj_desc->id)));
+ errmsg("large object %u was already dropped",
+ obj_desc->id)));
if (nbytes <= 0)
return 0;
+ /* this addition can't overflow because nbytes is only int32 */
if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
- elog(ERROR, "invalid write request size: %d", nbytes);
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid large object write request size: %d",
+ nbytes)));
open_lo_relation();
@@ -759,7 +777,18 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
if (!LargeObjectExists(obj_desc->id))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("large object %u was already dropped", obj_desc->id)));
+ errmsg("large object %u was already dropped",
+ obj_desc->id)));
+
+ /*
+ * use errmsg_internal here because we don't want to expose INT64_FORMAT
+ * in translatable strings; doing better is not worth the trouble
+ */
+ if (len < 0 || len > MAX_LARGE_OBJECT_SIZE)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg_internal("invalid large object truncation target: " INT64_FORMAT,
+ len)));
open_lo_relation();
diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt
index db8ab53af26..3e041649563 100644
--- a/src/backend/utils/errcodes.txt
+++ b/src/backend/utils/errcodes.txt
@@ -199,7 +199,6 @@ Section: Class 22 - Data Exception
2200N E ERRCODE_INVALID_XML_CONTENT invalid_xml_content
2200S E ERRCODE_INVALID_XML_COMMENT invalid_xml_comment
2200T E ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION invalid_xml_processing_instruction
-22P07 E ERRCODE_BLOB_OFFSET_OVERFLOW blob_offset_overflow
Section: Class 23 - Integrity Constraint Violation