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

Lines changed: 21 additions & 39 deletions
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

Lines changed: 52 additions & 23 deletions
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

Lines changed: 0 additions & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy