Skip to content

Commit d4e654d

Browse files
committed
Avoid invalid alloc size error in shm_mq
In shm_mq_receive(), a huge payload could trigger an unjustified "invalid memory alloc request size" error due to the way the buffer size is increased. Add error checks (documenting the upper limit) and avoid the error by limiting the allocation size to MaxAllocSize. Author: Markus Wanner <markus.wanner@2ndquadrant.com> Discussion: https://www.postgresql.org/message-id/flat/3bb363e7-ac04-0ac4-9fe8-db1148755bfa%402ndquadrant.com
1 parent 5c78f79 commit d4e654d

File tree

1 file changed

+24
-0
lines changed

1 file changed

+24
-0
lines changed

src/backend/storage/ipc/shm_mq.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "storage/procsignal.h"
2424
#include "storage/shm_mq.h"
2525
#include "storage/spin.h"
26+
#include "utils/memutils.h"
2627

2728
/*
2829
* This structure represents the actual queue, stored in shared memory.
@@ -359,6 +360,13 @@ shm_mq_sendv(shm_mq_handle *mqh, shm_mq_iovec *iov, int iovcnt, bool nowait)
359360
for (i = 0; i < iovcnt; ++i)
360361
nbytes += iov[i].len;
361362

363+
/* Prevent writing messages overwhelming the receiver. */
364+
if (nbytes > MaxAllocSize)
365+
ereport(ERROR,
366+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
367+
errmsg("cannot send a message of size %zu via shared memory queue",
368+
nbytes)));
369+
362370
/* Try to write, or finish writing, the length word into the buffer. */
363371
while (!mqh->mqh_length_word_complete)
364372
{
@@ -652,6 +660,17 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
652660
}
653661
nbytes = mqh->mqh_expected_bytes;
654662

663+
/*
664+
* Should be disallowed on the sending side already, but better check and
665+
* error out on the receiver side as well rather than trying to read a
666+
* prohibitively large message.
667+
*/
668+
if (nbytes > MaxAllocSize)
669+
ereport(ERROR,
670+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
671+
errmsg("invalid message size %zu in shared memory queue",
672+
nbytes)));
673+
655674
if (mqh->mqh_partial_bytes == 0)
656675
{
657676
/*
@@ -680,8 +699,13 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
680699
{
681700
Size newbuflen = Max(mqh->mqh_buflen, MQH_INITIAL_BUFSIZE);
682701

702+
/*
703+
* Double the buffer size until the payload fits, but limit to
704+
* MaxAllocSize.
705+
*/
683706
while (newbuflen < nbytes)
684707
newbuflen *= 2;
708+
newbuflen = Min(newbuflen, MaxAllocSize);
685709

686710
if (mqh->mqh_buffer != NULL)
687711
{

0 commit comments

Comments
 (0)