From 5a2f9cf910225f97d7f4df8316c0d3da29cd11c2 Mon Sep 17 00:00:00 2001
From: Xing Guo <higuoxing@gmail.com>
Date: Tue, 23 Jun 2026 14:38:59 +0800
Subject: [PATCH v1] PL/Perl: Fix NULL deref for forged array

A PL/Perl function returning a forged PostgreSQL::InServer::ARRAY
object (e.g., an empty hash blessed as that class) could cause a
segfault. This occurs because hv_fetch_string returns NULL pointer
when the "array" key is missing, and the code previously dereferenced
it without checking if the pointer itself was NULL.

This commit adds a NULL check before dereferencing the result of
hv_fetch_string, preventing the crash and properly returning an error.
A test case is also included to prevent regressions.
---
 src/pl/plperl/expected/plperl_array.out | 9 +++++++++
 src/pl/plperl/plperl.c                  | 2 +-
 src/pl/plperl/sql/plperl_array.sql      | 9 +++++++++
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/pl/plperl/expected/plperl_array.out b/src/pl/plperl/expected/plperl_array.out
index 260a55ea7e9..4bfaab733a9 100644
--- a/src/pl/plperl/expected/plperl_array.out
+++ b/src/pl/plperl/expected/plperl_array.out
@@ -274,3 +274,12 @@ select perl_setof_array('{{1}, {2}, {3}}');
  {3}
 (3 rows)
 
+-- Test NULL deref in get_perl_array_ref
+CREATE OR REPLACE FUNCTION test_null_deref_crash() RETURNS integer[] AS $$
+    my $h = {};
+    bless $h, 'PostgreSQL::InServer::ARRAY';
+    return $h;
+$$ LANGUAGE plperl;
+SELECT test_null_deref_crash();
+ERROR:  could not get array reference from PostgreSQL::InServer::ARRAY object
+CONTEXT:  PL/Perl function "test_null_deref_crash"
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index c1f9b8932a3..9ddb81d42b9 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1154,7 +1154,7 @@ get_perl_array_ref(SV *sv)
 			HV		   *hv = (HV *) SvRV(sv);
 			SV		  **sav = hv_fetch_string(hv, "array");
 
-			if (*sav && SvOK(*sav) && SvROK(*sav) &&
+			if (sav && *sav && SvOK(*sav) && SvROK(*sav) &&
 				SvTYPE(SvRV(*sav)) == SVt_PVAV)
 				return *sav;
 
diff --git a/src/pl/plperl/sql/plperl_array.sql b/src/pl/plperl/sql/plperl_array.sql
index ca63b5db625..248cafef726 100644
--- a/src/pl/plperl/sql/plperl_array.sql
+++ b/src/pl/plperl/sql/plperl_array.sql
@@ -206,3 +206,12 @@ create or replace function perl_setof_array(integer[]) returns setof integer[] l
 $$;
 
 select perl_setof_array('{{1}, {2}, {3}}');
+
+-- Test NULL deref in get_perl_array_ref
+CREATE OR REPLACE FUNCTION test_null_deref_crash() RETURNS integer[] AS $$
+    my $h = {};
+    bless $h, 'PostgreSQL::InServer::ARRAY';
+    return $h;
+$$ LANGUAGE plperl;
+
+SELECT test_null_deref_crash();
-- 
2.50.1 (Apple Git-155)

