v1-0001-jsonb_plperl-jsonb_plpython-Add-missing-check_sta.patch
text/x-patch
Filename: v1-0001-jsonb_plperl-jsonb_plpython-Add-missing-check_sta.patch
Type: text/x-patch
Part: 1
Patch
Format: format-patch
Series: patch v1-0001
Subject: jsonb_plperl, jsonb_plpython: Add missing check_stack_depth() calls
| File | + | − |
|---|---|---|
| contrib/jsonb_plperl/jsonb_plperl.c | 5 | 0 |
| contrib/jsonb_plpython/jsonb_plpython.c | 5 | 0 |
From 604409b67d55102c38ff5e735817c115e0073cc7 Mon Sep 17 00:00:00 2001
From: Aleksander Alekseev <aleksander@tigerdata.com>
Date: Tue, 16 Jun 2026 14:45:51 +0300
Subject: [PATCH v1 1/2] jsonb_plperl, jsonb_plpython: Add missing
check_stack_depth() calls
The functions responsible for converting JSONB to and from Perl and
Python values recurse mutually: Jsonb_to_SV() calls JsonbValue_to_SV()
which may call Jsonb_to_SV() again, and similarly SV_to_JsonbValue()
calls AV_to_JsonbValue() or HV_to_JsonbValue() which call
SV_to_JsonbValue() back. Likewise in jsonb_plpython.c.
Without a stack depth check, converting a deeply nested JSONB value
would cause a stack overflow and crash the backend process with SIGSEGV.
Add check_stack_depth() at the start of the entry function for each
recursion cycle so that an informative error is raised instead.
Note that while the JSON text parser already calls check_stack_depth()
during parsing, that protection does not cover JSONB values built via
jsonb_build_object() or other means that bypass the text parser.
Author: Aleksander Alekseev <aleksander@tigerdata.com>
Reviewed-by: TODO FIXME
Discussion: TODO FIXME
---
contrib/jsonb_plperl/jsonb_plperl.c | 5 +++++
contrib/jsonb_plpython/jsonb_plpython.c | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/contrib/jsonb_plperl/jsonb_plperl.c b/contrib/jsonb_plperl/jsonb_plperl.c
index f8e4a584fdd..fdcec7760da 100644
--- a/contrib/jsonb_plperl/jsonb_plperl.c
+++ b/contrib/jsonb_plperl/jsonb_plperl.c
@@ -3,6 +3,7 @@
#include <math.h>
#include "fmgr.h"
+#include "miscadmin.h"
#include "plperl.h"
#include "utils/fmgrprotos.h"
#include "utils/jsonb.h"
@@ -66,6 +67,8 @@ Jsonb_to_SV(JsonbContainer *jsonb)
JsonbIterator *it;
JsonbIteratorToken r;
+ check_stack_depth();
+
it = JsonbIteratorInit(jsonb);
r = JsonbIteratorNext(&it, &v, true);
@@ -179,6 +182,8 @@ SV_to_JsonbValue(SV *in, JsonbInState *jsonb_state, bool is_elem)
dTHX;
JsonbValue out; /* result */
+ check_stack_depth();
+
/* Dereference references recursively. */
while (SvROK(in))
in = SvRV(in);
diff --git a/contrib/jsonb_plpython/jsonb_plpython.c b/contrib/jsonb_plpython/jsonb_plpython.c
index 4de75a04e76..f6eddb81c48 100644
--- a/contrib/jsonb_plpython/jsonb_plpython.c
+++ b/contrib/jsonb_plpython/jsonb_plpython.c
@@ -1,5 +1,6 @@
#include "postgres.h"
+#include "miscadmin.h"
#include "plpy_elog.h"
#include "plpy_typeio.h"
#include "plpy_util.h"
@@ -143,6 +144,8 @@ PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
JsonbIterator *it;
PyObject *result;
+ check_stack_depth();
+
it = JsonbIteratorInit(jsonb);
r = JsonbIteratorNext(&it, &v, true);
@@ -410,6 +413,8 @@ PLyObject_ToJsonbValue(PyObject *obj, JsonbInState *jsonb_state, bool is_elem)
{
JsonbValue *out;
+ check_stack_depth();
+
if (!PyUnicode_Check(obj))
{
if (PySequence_Check(obj))
--
2.43.0