| From: | Andrey Rachitskiy <pl0h0yp1(at)gmail(dot)com> |
|---|---|
| To: | |
| Cc: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Nikolay Shaplov <dhyan(at)nataraj(dot)su> |
| Subject: | [PATCH] Limit PL/Perl scalar copies to work_mem |
| Date: | 2026-07-06 22:41:57 |
| Message-ID: | 20260707034157.5e88bf34@pg-ThinkPad-T14-Gen-4 |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
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
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-plperl-limit-scalar-size.patch | text/x-patch | 3.7 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Fujii Masao | 2026-07-06 22:43:50 | Re: Fix HAVING-to-WHERE pushdown with mismatched operator families |
| Previous Message | Mario González Troncoso | 2026-07-06 22:31:44 | Re: Possible replace of strncpy on xactdesc.c |