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

