diff options
| author | Tom Lane | 2012-10-08 22:24:06 +0000 |
|---|---|---|
| committer | Tom Lane | 2012-10-08 22:24:32 +0000 |
| commit | 26fe56481c0f7baa705f0b3265b5a0676f894a94 (patch) | |
| tree | 60bfe35565e16c168915e10500f3b61440f7865f /src/backend | |
| parent | 878daf2e72755feadbfb8d21aad26dafd8658086 (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.c | 60 | ||||
| -rw-r--r-- | src/backend/storage/large_object/inv_api.c | 75 | ||||
| -rw-r--r-- | src/backend/utils/errcodes.txt | 1 |
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 |
