Thread

  1. [PATCH] Limit PL/Perl scalar copies to work_mem

    Andrey Rachitskiy <pl0h0yp1@gmail.com> — 2026-07-06T22:41:57Z

    
    Hi, Hackers!
    
    When a PL/Perl function returns a large text value, sv2cstr() copies the
    entire Perl string into backend memory with no size check.  The helper
    is used on the path from Perl return values and SPI arguments to
    PostgreSQL text datums; it simply palloc()s a copy after SvPVutf8().
    A user who is allowed to create untrusted PL/Perl functions can
    therefore force the backend to allocate strings far larger than any
    session limit. On a memory-constrained host this can get the backend
    process killed by the OOM killer (SIGKILL) rather than raising a
    catchable PostgreSQL error.
    
    Reproducer (unpatched master, plperl enabled):
    
    CREATE FUNCTION perl_huge_text() RETURNS text LANGUAGE plperl
    AS $$ return 'x' x (1024 * 1024 * 1024);
      $$;
      SELECT perl_huge_text();
    
    On a container limited to about 768MB RAM, CREATE FUNCTION alone is
    enough to lose the backend:
    
      LOG:  client backend (PID ...) was terminated by signal 9: Killed
      DETAIL:  Failed process was running: CREATE OR REPLACE FUNCTION ...
    
    With plenty of free RAM the same code may succeed instead, which I think
    shows missing enforcement rather than an intentional "no limit" design:
    other PL/Perl paths already enforce bounds (MAXDIM, AV_SIZE_MAX for SPI
    results, max_stack_depth in recursive conversion), but sv2cstr() had
    none.
    
    This patch rejects Perl strings larger than work_mem * 1024 bytes,
    capped by MaxAllocSize, before copying them through sv2cstr().  That
    follows the same work_mem-based pattern used elsewhere in the backend
    for per-query working storage.  The check is done after SvPVutf8() has
    reported the length but before utf_u2e() allocates the
    database-encoding copy. A plperl regression test returns a 16MB string
    with the default 4MB work_mem and expects:
    
      ERROR:  Perl value exceeds maximum allowed size (4194304 bytes)
      HINT:  Increase work_mem or reduce the result size.
    
    Legitimate functions that need to move more data can raise work_mem for
    the session, consistent with other operations bounded by that GUC.
    
    Comments welcome.
    
    -- 
    Regards,
    Andrey Rachitskiy
    
    
  2. Re: [PATCH] Limit PL/Perl scalar copies to work_mem

    Tom Lane <tgl@sss.pgh.pa.us> — 2026-07-07T01:56:17Z

    Andrey Rachitskiy <pl0h0yp1@gmail.com> writes:
    > When a PL/Perl function returns a large text value, sv2cstr() copies the
    > entire Perl string into backend memory with no size check.  The helper
    > is used on the path from Perl return values and SPI arguments to
    > PostgreSQL text datums; it simply palloc()s a copy after SvPVutf8().
    > A user who is allowed to create untrusted PL/Perl functions can
    > therefore force the backend to allocate strings far larger than any
    > session limit. On a memory-constrained host this can get the backend
    > process killed by the OOM killer (SIGKILL) rather than raising a
    > catchable PostgreSQL error.
    
    This is true of very many operations in PG, not only PL/Perl.
    Our general answer to that is to disable memory overcommit
    so that the OOM killer won't apply.  One should also note that
    the same PL/Perl function can (try to) allocate enormous amounts
    of memory entirely within Perl, where we have no ability to stop
    it.  I don't see how constraining the size of a function result
    string helps noticeably.
    
    > This patch rejects Perl strings larger than work_mem * 1024 bytes,
    
    Our normal understanding of work_mem is that it's a point beyond which
    we'll spill to disk, or otherwise try to reduce our memory consumption
    at the cost of longer runtime.  Not a point at which an outright query
    failure is OK.
    
    So, even if I thought this were something we should address,
    I don't believe this is an appropriate approach to a fix.
    
    			regards, tom lane
    
    
    
    
  3. Re: [PATCH] Limit PL/Perl scalar copies to work_mem

    Andrey Rachitskiy <pl0h0yp1@gmail.com> — 2026-07-07T05:44:45Z

    Thanks for the review, Tom.
    
    You're right that work_mem is a poor fit for a hard failure here, and
    more generally that this isn't the sort of problem PL/Perl can solve
    with a small boundary check alone.  I should have raised the idea on
    the list for discussion before sending a patch — I'll do that next time
    rather than charging ahead with a fix.
    
    Thanks for the feedback.
    
    
    On Mon, 06 Jul 2026 21:56:17 -0400, Tom Lane <tgl@sss.pgh.pa.us> wrote:
    
    > Andrey Rachitskiy <pl0h0yp1@gmail.com> writes:
    > > When a PL/Perl function returns a large text value, sv2cstr()
    > > copies the entire Perl string into backend memory with no size
    > > check.  The helper is used on the path from Perl return values and
    > > SPI arguments to PostgreSQL text datums; it simply palloc()s a copy
    > > after SvPVutf8(). A user who is allowed to create untrusted PL/Perl
    > > functions can therefore force the backend to allocate strings far
    > > larger than any session limit. On a memory-constrained host this
    > > can get the backend process killed by the OOM killer (SIGKILL)
    > > rather than raising a catchable PostgreSQL error.
    > 
    > This is true of very many operations in PG, not only PL/Perl.
    > Our general answer to that is to disable memory overcommit
    > so that the OOM killer won't apply.  One should also note that
    > the same PL/Perl function can (try to) allocate enormous amounts
    > of memory entirely within Perl, where we have no ability to stop
    > it.  I don't see how constraining the size of a function result
    > string helps noticeably.
    > 
    > > This patch rejects Perl strings larger than work_mem * 1024 bytes,
    > 
    > Our normal understanding of work_mem is that it's a point beyond which
    > we'll spill to disk, or otherwise try to reduce our memory consumption
    > at the cost of longer runtime.  Not a point at which an outright query
    > failure is OK.
    > 
    > So, even if I thought this were something we should address,
    > I don't believe this is an appropriate approach to a fix.
    > 
    > 			regards, tom lane
    
    
    
    -- 
    Regards,
    Andrey Rachitskiy