Skip to content

Commit 26ec6b5

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 afa0d53 commit 26ec6b5

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
@@ -24,6 +24,7 @@
2424
#include "storage/procsignal.h"
2525
#include "storage/shm_mq.h"
2626
#include "storage/spin.h"
27+
#include "utils/memutils.h"
2728

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

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

686+
/*
687+
* Should be disallowed on the sending side already, but better check and
688+
* error out on the receiver side as well rather than trying to read a
689+
* prohibitively large message.
690+
*/
691+
if (nbytes > MaxAllocSize)
692+
ereport(ERROR,
693+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
694+
errmsg("invalid message size %zu in shared memory queue",
695+
nbytes)));
696+
678697
if (mqh->mqh_partial_bytes == 0)
679698
{
680699
/*
@@ -703,8 +722,13 @@ shm_mq_receive(shm_mq_handle *mqh, Size *nbytesp, void **datap, bool nowait)
703722
{
704723
Size newbuflen = Max(mqh->mqh_buflen, MQH_INITIAL_BUFSIZE);
705724

725+
/*
726+
* Double the buffer size until the payload fits, but limit to
727+
* MaxAllocSize.
728+
*/
706729
while (newbuflen < nbytes)
707730
newbuflen *= 2;
731+
newbuflen = Min(newbuflen, MaxAllocSize);
708732

709733
if (mqh->mqh_buffer != NULL)
710734
{

0 commit comments

Comments
 (0)