public inbox for [email protected]  
help / color / mirror / Atom feed
From: Andrey Rachitskiy <[email protected]>
To: [email protected]
To: [email protected]
Cc: [email protected]
Subject: Re: BUG #19458: OOM killer in jsonb_path_exists_opr (@?) with malformed JSONPath containing non-existent variables
Date: Mon, 20 Apr 2026 18:38:38 +0500
Message-ID: <CAB8bMit1HvJsAasUYwmq+82Oa3zQhJyvsHNS4PGF_S_BCMnuVA@mail.gmail.com> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>

I propose a targeted backpatch for REL_14/15/16 in jsonpath_exec.c to align
missing variable handling with newer branches and prevent pathological
memory growth on malformed/hostile jsonpath expressions.

Why this is not a full backport
This is intentionally not a full backport of the REL_17 jsonpath executor
refactoring (callbacks for variable access, broader executor integration,
etc.).

Why this still fixes the reported issue
On REL_14/15/16, with current behavior (missing vars -> null), some crafted
jsonpath expressions continue deep evaluation and can consume very large
memory, leading to OOM.
With this patch, execution fails early on undefined variable, matching
REL_17 behavior for this case and avoiding runaway memory use.

—
Regards,
Andrey Rachitskiy
Postgres Professional

пт, 17 апр. 2026 г. в 16:21, PG Bug reporting form <[email protected]>:

> The following bug has been logged on the website:
>
> Bug reference:      19458
> Logged by:          Andrey Rachitskiy
> Email address:      [email protected]
> PostgreSQL version: 14.22
> Operating system:   Debian GNU/Linux 12 (bookworm)
> Description:
>
> Description:
> During fuzzing of the jsonb_path_exists_opr (operator jsonb @? jsonpath, a
> two-argument version of jsonb_path_exists()), a pathological query was
> discovered that causes uncontrolled memory consumption, leading to OOM
> Killer on PostgreSQL versions REL_14/15/16_STABLE.
> On versions 17 and 18, the same query returns a proper error instead of
> crashing the server.
> This bug was found using AFL++ as a fuzzer and LibBlobStamper as a tool for
> creating syntactically correct arguments.
>
> Reproduction:
> Execute the following query:
> ```sql
> select '[3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 13558284848669739, 3472328296227668016, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328295419228208, 3472328296227680304,
> 3528904766546522246, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296328343600,
> 3472328296227680304, 3472328296227680299, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3470920921344127024, 3906362710315511856,
> 3472328296228075062, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472334893297446960, 3472328090069248816,
> 13511005849006128, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 3472328296227680304, 3472328296227680304, 3472328296227680304,
> 13563782407139376, 4337019423877509168]'::jsonb @? '(-$?(0 <
> ($"〰〭〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰" - $?(0 < $"〰〰〰〰〰〰〰〰〰〰〰〰〰〰" - $?(0 + $ <
> $"㘰〰㘶〰")."〰〰〰〰")."〰〰〰〰〰〰〰〰") - 0?(+$ < $"〰
>
> 〰〰〰")."ほ〰〰㘰")."〰〰〰〶〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰")'::jsonpath;
> ```
>
> Expected result:
> The query should return an error, as happens on versions 17 and 18:
> ERROR:  could not find jsonpath variable "〰〭〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰〰"
>
> Actual result (14, 15, 16):
>   - Memory consumption grows until the kernel kills the postgres process
> via
> OOM Killer
>   - Client loses connection:
>        server closed the connection unexpectedly
>        This probably means the server terminated abnormally
>        before or while processing the request.
>
> Kernel log:
> 516294.487767] Out of memory: Killed process 1135405 (postgres)
> total-vm:13521932kB, anon-rss:9170792kB, file-rss:92kB, shmem-rss:1848kB,
> UID:1002 pgtables:26176kB oom_score_adj:0
>
> --
> Regards,
> Andrey Rachitskiy
> Postgres Professional
>
>
>


Attachments:

  [application/octet-stream] jsonpath-fix-null-comparison.patch (768B, 3-jsonpath-fix-null-comparison.patch)
  download | inline diff:
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 10ec66c6293..34420849eac 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -2128,14 +2128,15 @@ getJsonPathVariable(JsonPathExecContext *cxt, JsonPathItem *variable,
 	JsonbValue	tmp;
 	JsonbValue *v;
 
-	if (!vars)
-	{
-		value->type = jbvNull;
-		return;
-	}
-
 	Assert(variable->type == jpiVariable);
 	varName = jspGetString(variable, &varNameLength);
+
+	if (!vars)
+		ereport(ERROR,
+			(errcode(ERRCODE_UNDEFINED_OBJECT),
+			 errmsg("could not find jsonpath variable \"%s\"",
+					pnstrdup(varName, varNameLength))));
+
 	tmp.type = jbvString;
 	tmp.val.string.val = varName;
 	tmp.val.string.len = varNameLength;


reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: BUG #19458: OOM killer in jsonb_path_exists_opr (@?) with malformed JSONPath containing non-existent variables
  In-Reply-To: <CAB8bMit1HvJsAasUYwmq+82Oa3zQhJyvsHNS4PGF_S_BCMnuVA@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox