Skip to content

Commit d27c18d

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 da129a0 commit d27c18d

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
{
@@ -624,6 +632,17 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
624632
}
625633
nbytes = mqh->mqh_expected_bytes;
626634

635+
/*
636+
* Should be disallowed on the sending side already, but better check and
637+
* error out on the receiver side as well rather than trying to read a
638+
* prohibitively large message.
639+
*/
640+
if (nbytes > MaxAllocSize)
641+
ereport(ERROR,
642+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
643+
errmsg("invalid message size %zu in shared memory queue",
644+
nbytes)));
645+
627646
if (mqh->mqh_partial_bytes == 0)
628647
{
629648
/*
@@ -652,8 +671,13 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
652671
{
653672
Size newbuflen = Max(mqh->mqh_buflen, MQH_INITIAL_BUFSIZE);
654673

674+
/*
675+
* Double the buffer size until the payload fits, but limit to
676+
* MaxAllocSize.
677+
*/
655678
while (newbuflen < nbytes)
656679
newbuflen *= 2;
680+
newbuflen = Min(newbuflen, MaxAllocSize);
657681

658682
if (mqh->mqh_buffer != NULL)
659683
{

0 commit comments

Comments
 (0)