Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 26fe564

Browse files
committed
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.
1 parent 878daf2 commit 26fe564

File tree

9 files changed

+215
-171
lines changed

9 files changed

+215
-171
lines changed

src/backend/libpq/be-fsstubs.c

+21-39
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
#include "postgres.h"
4040

4141
#include <fcntl.h>
42-
#include <limits.h>
4342
#include <sys/stat.h>
4443
#include <unistd.h>
4544

@@ -57,7 +56,9 @@
5756
*/
5857
bool lo_compat_privileges;
5958

60-
/*#define FSDB 1*/
59+
/* define this to enable debug logging */
60+
/* #define FSDB 1 */
61+
/* chunk size for lo_import/lo_export transfers */
6162
#define BUFSIZE 8192
6263

6364
/*
@@ -210,7 +211,6 @@ lo_write(int fd, const char *buf, int len)
210211
return status;
211212
}
212213

213-
214214
Datum
215215
lo_lseek(PG_FUNCTION_ARGS)
216216
{
@@ -226,42 +226,31 @@ lo_lseek(PG_FUNCTION_ARGS)
226226

227227
status = inv_seek(cookies[fd], offset, whence);
228228

229-
if (INT_MAX < status)
230-
{
229+
/* guard against result overflow */
230+
if (status != (int32) status)
231231
ereport(ERROR,
232-
(errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
233-
errmsg("offset overflow: %d", fd)));
234-
PG_RETURN_INT32(-1);
235-
}
232+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
233+
errmsg("lo_lseek result out of range for large-object descriptor %d",
234+
fd)));
236235

237-
PG_RETURN_INT32(status);
236+
PG_RETURN_INT32((int32) status);
238237
}
239238

240-
241239
Datum
242240
lo_lseek64(PG_FUNCTION_ARGS)
243241
{
244242
int32 fd = PG_GETARG_INT32(0);
245243
int64 offset = PG_GETARG_INT64(1);
246244
int32 whence = PG_GETARG_INT32(2);
247-
MemoryContext currentContext;
248-
int64 status;
245+
int64 status;
249246

250247
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
251-
{
252248
ereport(ERROR,
253249
(errcode(ERRCODE_UNDEFINED_OBJECT),
254250
errmsg("invalid large-object descriptor: %d", fd)));
255-
PG_RETURN_INT64(-1);
256-
}
257-
258-
Assert(fscxt != NULL);
259-
currentContext = MemoryContextSwitchTo(fscxt);
260251

261252
status = inv_seek(cookies[fd], offset, whence);
262253

263-
MemoryContextSwitchTo(currentContext);
264-
265254
PG_RETURN_INT64(status);
266255
}
267256

@@ -301,7 +290,7 @@ Datum
301290
lo_tell(PG_FUNCTION_ARGS)
302291
{
303292
int32 fd = PG_GETARG_INT32(0);
304-
int64 offset = 0;
293+
int64 offset;
305294

306295
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
307296
ereport(ERROR,
@@ -310,37 +299,30 @@ lo_tell(PG_FUNCTION_ARGS)
310299

311300
offset = inv_tell(cookies[fd]);
312301

313-
if (INT_MAX < offset)
314-
{
302+
/* guard against result overflow */
303+
if (offset != (int32) offset)
315304
ereport(ERROR,
316-
(errcode(ERRCODE_BLOB_OFFSET_OVERFLOW),
317-
errmsg("offset overflow: %d", fd)));
318-
PG_RETURN_INT32(-1);
319-
}
305+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
306+
errmsg("lo_tell result out of range for large-object descriptor %d",
307+
fd)));
320308

321-
PG_RETURN_INT32(offset);
309+
PG_RETURN_INT32((int32) offset);
322310
}
323311

324-
325312
Datum
326313
lo_tell64(PG_FUNCTION_ARGS)
327314
{
328315
int32 fd = PG_GETARG_INT32(0);
316+
int64 offset;
329317

330318
if (fd < 0 || fd >= cookies_size || cookies[fd] == NULL)
331-
{
332319
ereport(ERROR,
333320
(errcode(ERRCODE_UNDEFINED_OBJECT),
334321
errmsg("invalid large-object descriptor: %d", fd)));
335-
PG_RETURN_INT64(-1);
336-
}
337322

338-
/*
339-
* We assume we do not need to switch contexts for inv_tell. That is
340-
* true for now, but is probably more than this module ought to
341-
* assume...
342-
*/
343-
PG_RETURN_INT64(inv_tell(cookies[fd]));
323+
offset = inv_tell(cookies[fd]);
324+
325+
PG_RETURN_INT64(offset);
344326
}
345327

346328
Datum

src/backend/storage/large_object/inv_api.c

+52-23
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
*/
3131
#include "postgres.h"
3232

33+
#include <limits.h>
34+
3335
#include "access/genam.h"
3436
#include "access/heapam.h"
3537
#include "access/sysattr.h"
@@ -264,7 +266,10 @@ inv_open(Oid lobjId, int flags, MemoryContext mcxt)
264266
retval->flags = IFS_RDLOCK;
265267
}
266268
else
267-
elog(ERROR, "invalid flags: %d", flags);
269+
ereport(ERROR,
270+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
271+
errmsg("invalid flags for opening a large object: %d",
272+
flags)));
268273

269274
/* Can't use LargeObjectExists here because it always uses SnapshotNow */
270275
if (!myLargeObjectExists(lobjId, retval->snapshot))
@@ -381,34 +386,45 @@ inv_getsize(LargeObjectDesc *obj_desc)
381386
int64
382387
inv_seek(LargeObjectDesc *obj_desc, int64 offset, int whence)
383388
{
389+
int64 newoffset;
390+
384391
Assert(PointerIsValid(obj_desc));
385392

393+
/*
394+
* Note: overflow in the additions is possible, but since we will reject
395+
* negative results, we don't need any extra test for that.
396+
*/
386397
switch (whence)
387398
{
388399
case SEEK_SET:
389-
if (offset < 0 || offset >= MAX_LARGE_OBJECT_SIZE)
390-
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
391-
obj_desc->offset = offset;
400+
newoffset = offset;
392401
break;
393402
case SEEK_CUR:
394-
if ((offset + obj_desc->offset) < 0 ||
395-
(offset + obj_desc->offset) >= MAX_LARGE_OBJECT_SIZE)
396-
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
397-
obj_desc->offset += offset;
403+
newoffset = obj_desc->offset + offset;
398404
break;
399405
case SEEK_END:
400-
{
401-
int64 pos = inv_getsize(obj_desc) + offset;
402-
403-
if (pos < 0 || pos >= MAX_LARGE_OBJECT_SIZE)
404-
elog(ERROR, "invalid seek offset: " INT64_FORMAT, offset);
405-
obj_desc->offset = pos;
406-
}
406+
newoffset = inv_getsize(obj_desc) + offset;
407407
break;
408408
default:
409-
elog(ERROR, "invalid whence: %d", whence);
409+
ereport(ERROR,
410+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
411+
errmsg("invalid whence setting: %d", whence)));
412+
newoffset = 0; /* keep compiler quiet */
413+
break;
410414
}
411-
return obj_desc->offset;
415+
416+
/*
417+
* use errmsg_internal here because we don't want to expose INT64_FORMAT
418+
* in translatable strings; doing better is not worth the trouble
419+
*/
420+
if (newoffset < 0 || newoffset > MAX_LARGE_OBJECT_SIZE)
421+
ereport(ERROR,
422+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
423+
errmsg_internal("invalid large object seek target: " INT64_FORMAT,
424+
newoffset)));
425+
426+
obj_desc->offset = newoffset;
427+
return newoffset;
412428
}
413429

414430
int64
@@ -438,9 +454,6 @@ inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes)
438454
if (nbytes <= 0)
439455
return 0;
440456

441-
if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
442-
elog(ERROR, "invalid read request size: %d", nbytes);
443-
444457
open_lo_relation();
445458

446459
ScanKeyInit(&skey[0],
@@ -559,13 +572,18 @@ inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes)
559572
if (!LargeObjectExists(obj_desc->id))
560573
ereport(ERROR,
561574
(errcode(ERRCODE_UNDEFINED_OBJECT),
562-
errmsg("large object %u was already dropped", obj_desc->id)));
575+
errmsg("large object %u was already dropped",
576+
obj_desc->id)));
563577

564578
if (nbytes <= 0)
565579
return 0;
566580

581+
/* this addition can't overflow because nbytes is only int32 */
567582
if ((nbytes + obj_desc->offset) > MAX_LARGE_OBJECT_SIZE)
568-
elog(ERROR, "invalid write request size: %d", nbytes);
583+
ereport(ERROR,
584+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
585+
errmsg("invalid large object write request size: %d",
586+
nbytes)));
569587

570588
open_lo_relation();
571589

@@ -759,7 +777,18 @@ inv_truncate(LargeObjectDesc *obj_desc, int64 len)
759777
if (!LargeObjectExists(obj_desc->id))
760778
ereport(ERROR,
761779
(errcode(ERRCODE_UNDEFINED_OBJECT),
762-
errmsg("large object %u was already dropped", obj_desc->id)));
780+
errmsg("large object %u was already dropped",
781+
obj_desc->id)));
782+
783+
/*
784+
* use errmsg_internal here because we don't want to expose INT64_FORMAT
785+
* in translatable strings; doing better is not worth the trouble
786+
*/
787+
if (len < 0 || len > MAX_LARGE_OBJECT_SIZE)
788+
ereport(ERROR,
789+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
790+
errmsg_internal("invalid large object truncation target: " INT64_FORMAT,
791+
len)));
763792

764793
open_lo_relation();
765794

src/backend/utils/errcodes.txt

-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,6 @@ Section: Class 22 - Data Exception
199199
2200N E ERRCODE_INVALID_XML_CONTENT invalid_xml_content
200200
2200S E ERRCODE_INVALID_XML_COMMENT invalid_xml_comment
201201
2200T E ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION invalid_xml_processing_instruction
202-
22P07 E ERRCODE_BLOB_OFFSET_OVERFLOW blob_offset_overflow
203202

204203
Section: Class 23 - Integrity Constraint Violation
205204

src/include/catalog/pg_proc.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ DATA(insert OID = 955 ( lowrite PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 23
10401040
DESCR("large object write");
10411041
DATA(insert OID = 956 ( lo_lseek PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 23 "23 23 23" _null_ _null_ _null_ _null_ lo_lseek _null_ _null_ _null_ ));
10421042
DESCR("large object seek");
1043-
DATA(insert OID = 3170 ( lo_lseek64 PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 20 "23 20 23" _null_ _null_ _null_ _null_ lo_lseek64 _null_ _null_ _null_ ));
1043+
DATA(insert OID = 3170 ( lo_lseek64 PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 20 "23 20 23" _null_ _null_ _null_ _null_ lo_lseek64 _null_ _null_ _null_ ));
10441044
DESCR("large object seek (64 bit)");
10451045
DATA(insert OID = 957 ( lo_creat PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 26 "23" _null_ _null_ _null_ _null_ lo_creat _null_ _null_ _null_ ));
10461046
DESCR("large object create");

0 commit comments

Comments
 (0)