Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0e924c0

Browse files
committed
Fix lo_read, lo_write, lo_truncate to cope with "size_t" length parameters.
libpq defines these functions as accepting "size_t" lengths ... but theunderlying backend functions expect signed int32 length parameters, and sowill misinterpret any value exceeding INT_MAX. Fix the libpq side to throwerror rather than possibly doing something unexpected.This is a bug of long standing, but I doubt it's worth back-patching. Theproblem is really pretty academic anyway with lo_read/lo_write, since anycaller expecting sane behavior would have to have provided a multi-gigabytebuffer. It's slightly more pressing with lo_truncate, but still we haven'tsupported large objects over 2GB until now.
1 parentb6d4522 commit0e924c0

File tree

2 files changed

+90
-16
lines changed

2 files changed

+90
-16
lines changed

‎doc/src/sgml/lobj.sgml

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,17 @@
6969
access reads and writes.
7070
</para>
7171

72+
<para>
73+
The chunks stored for a large object do not have to be contiguous.
74+
For example, if an application opens a new large object, seeks to offset
75+
1000000, and writes a few bytes there, this does not result in allocation
76+
of 1000000 bytes worth of storage; only of chunks covering the range of
77+
data bytes actually written. A read operation will, however, read out
78+
zeroes for any unallocated locations preceding the last existing chunk.
79+
This corresponds to the common behavior of <quote>sparsely allocated</>
80+
files in <acronym>Unix</acronym> file systems.
81+
</para>
82+
7283
<para>
7384
As of <productname>PostgreSQL</> 9.0, large objects have an owner
7485
and a set of access permissions, which can be managed using
@@ -299,11 +310,19 @@ inv_fd = lo_open(conn, inv_oid, INV_READ|INV_WRITE);
299310
int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
300311
</synopsis>
301312
writes <parameter>len</parameter> bytes from <parameter>buf</parameter>
302-
to large object descriptor <parameter>fd</>. The <parameter>fd</parameter>
303-
argument must have been returned by a previous
304-
<function>lo_open</function>. The number of bytes actually
305-
written is returned. In the event of an error, the return value
306-
is -1.
313+
(which must be of size <parameter>len</parameter>) to large object
314+
descriptor <parameter>fd</>. The <parameter>fd</parameter> argument must
315+
have been returned by a previous <function>lo_open</function>. The
316+
number of bytes actually written is returned (in the current
317+
implementation, this will always equal <parameter>len</parameter> unless
318+
there is an error). In the event of an error, the return value is -1.
319+
</para>
320+
321+
<para>
322+
Although the <parameter>len</parameter> parameter is declared as
323+
<type>size_t</>, this function will reject length values larger than
324+
<literal>INT_MAX</>. In practice, it's best to transfer data in chunks
325+
of at most a few megabytes anyway.
307326
</para>
308327
</sect2>
309328

@@ -316,13 +335,22 @@ int lo_write(PGconn *conn, int fd, const char *buf, size_t len);
316335
<synopsis>
317336
int lo_read(PGconn *conn, int fd, char *buf, size_t len);
318337
</synopsis>
319-
reads <parameter>len</parameter> bytes from large object descriptor
320-
<parameter>fd</parameter> into <parameter>buf</parameter>. The
321-
<parameter>fd</parameter> argument must have been returned by a
322-
previous <function>lo_open</function>. The number of bytes
323-
actually read is returned. In the event of an error, the return
338+
reads up to <parameter>len</parameter> bytes from large object descriptor
339+
<parameter>fd</parameter> into <parameter>buf</parameter> (which must be
340+
of size <parameter>len</parameter>). The <parameter>fd</parameter>
341+
argument must have been returned by a previous
342+
<function>lo_open</function>. The number of bytes actually read is
343+
returned; this will be less than <parameter>len</parameter> if the end of
344+
the large object is reached first. In the event of an error, the return
324345
value is -1.
325346
</para>
347+
348+
<para>
349+
Although the <parameter>len</parameter> parameter is declared as
350+
<type>size_t</>, this function will reject length values larger than
351+
<literal>INT_MAX</>. In practice, it's best to transfer data in chunks
352+
of at most a few megabytes anyway.
353+
</para>
326354
</sect2>
327355

328356
<sect2 id="lo-seek">
@@ -416,7 +444,7 @@ int lo_truncate(PGcon *conn, int fd, size_t len);
416444
<parameter>fd</parameter> argument must have been returned by a
417445
previous <function>lo_open</function>. If <parameter>len</> is
418446
greater than the large object's current length, the large object
419-
is extended with null bytes ('\0').
447+
is extendedto the specified lengthwith null bytes ('\0').
420448
On success, <function>lo_truncate</function> returns
421449
zero. On error, the return value is -1.
422450
</para>
@@ -426,6 +454,12 @@ int lo_truncate(PGcon *conn, int fd, size_t len);
426454
<parameter>fd</parameter> is not changed.
427455
</para>
428456

457+
<para>
458+
Although the <parameter>len</parameter> parameter is declared as
459+
<type>size_t</>, <function>lo_truncate</function> will reject length
460+
values larger than <literal>INT_MAX</>.
461+
</para>
462+
429463
<para>
430464
<indexterm><primary>lo_truncate64</></>
431465
When dealing with large objects that might exceed 2GB in size,

‎src/interfaces/libpq/fe-lobj.c

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#endif
3232

3333
#include<fcntl.h>
34+
#include<limits.h>
3435
#include<sys/stat.h>
3536
#include<netinet/in.h>/* for ntohl/htonl */
3637
#include<arpa/inet.h>
@@ -155,13 +156,29 @@ lo_truncate(PGconn *conn, int fd, size_t len)
155156
return-1;
156157
}
157158

159+
/*
160+
* Long ago, somebody thought it'd be a good idea to declare this function
161+
* as taking size_t ... but the underlying backend function only accepts a
162+
* signed int32 length. So throw error if the given value overflows
163+
* int32. (A possible alternative is to automatically redirect the call
164+
* to lo_truncate64; but if the caller wanted to rely on that backend
165+
* function being available, he could have called lo_truncate64 for
166+
* himself.)
167+
*/
168+
if (len> (size_t)INT_MAX)
169+
{
170+
printfPQExpBuffer(&conn->errorMessage,
171+
libpq_gettext("argument of lo_truncate exceeds integer range\n"));
172+
return-1;
173+
}
174+
158175
argv[0].isint=1;
159176
argv[0].len=4;
160177
argv[0].u.integer=fd;
161178

162179
argv[1].isint=1;
163180
argv[1].len=4;
164-
argv[1].u.integer=len;
181+
argv[1].u.integer=(int)len;
165182

166183
res=PQfn(conn,conn->lobjfuncs->fn_lo_truncate,
167184
&retval,&result_len,1,argv,2);
@@ -251,13 +268,26 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len)
251268
return-1;
252269
}
253270

271+
/*
272+
* Long ago, somebody thought it'd be a good idea to declare this function
273+
* as taking size_t ... but the underlying backend function only accepts a
274+
* signed int32 length. So throw error if the given value overflows
275+
* int32.
276+
*/
277+
if (len> (size_t)INT_MAX)
278+
{
279+
printfPQExpBuffer(&conn->errorMessage,
280+
libpq_gettext("argument of lo_read exceeds integer range\n"));
281+
return-1;
282+
}
283+
254284
argv[0].isint=1;
255285
argv[0].len=4;
256286
argv[0].u.integer=fd;
257287

258288
argv[1].isint=1;
259289
argv[1].len=4;
260-
argv[1].u.integer=len;
290+
argv[1].u.integer=(int)len;
261291

262292
res=PQfn(conn,conn->lobjfuncs->fn_lo_read,
263293
(int*)buf,&result_len,0,argv,2);
@@ -293,15 +323,25 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len)
293323
return-1;
294324
}
295325

296-
if (len <=0)
297-
return0;
326+
/*
327+
* Long ago, somebody thought it'd be a good idea to declare this function
328+
* as taking size_t ... but the underlying backend function only accepts a
329+
* signed int32 length. So throw error if the given value overflows
330+
* int32.
331+
*/
332+
if (len> (size_t)INT_MAX)
333+
{
334+
printfPQExpBuffer(&conn->errorMessage,
335+
libpq_gettext("argument of lo_write exceeds integer range\n"));
336+
return-1;
337+
}
298338

299339
argv[0].isint=1;
300340
argv[0].len=4;
301341
argv[0].u.integer=fd;
302342

303343
argv[1].isint=0;
304-
argv[1].len=len;
344+
argv[1].len=(int)len;
305345
argv[1].u.ptr= (int*)buf;
306346

307347
res=PQfn(conn,conn->lobjfuncs->fn_lo_write,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp