aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2018-06-18 15:55:06 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2018-06-18 15:55:06 -0400
commit7594b7a53366f6c262103acd161e6fee0a30e5c2 (patch)
tree72fcfba6b3d72a1df35e1a760962e2ab5567fea7
parentfb28104a4baa5488e89fbd7ec2cc7dce1a90fce6 (diff)
downloadpostgresql-7594b7a53366f6c262103acd161e6fee0a30e5c2.tar.gz
postgresql-7594b7a53366f6c262103acd161e6fee0a30e5c2.zip
Fix contrib/hstore_plperl to look through scalar refs.
Bring this transform function into sync with the policy established by commit 3a382983d. Also, fix it to make sure that what it drills down to is indeed a hash, and not some other kind of Perl SV. Previously, the test cases added here provoked crashes. Because of the crash hazard, back-patch to 9.5 where this module was introduced. Discussion: https://postgr.es/m/28336.1528393969@sss.pgh.pa.us
-rw-r--r--contrib/hstore_plperl/expected/hstore_plperl.out19
-rw-r--r--contrib/hstore_plperl/hstore_plperl.c14
-rw-r--r--contrib/hstore_plperl/sql/hstore_plperl.sql19
3 files changed, 51 insertions, 1 deletions
diff --git a/contrib/hstore_plperl/expected/hstore_plperl.out b/contrib/hstore_plperl/expected/hstore_plperl.out
index 25fc506c23f..1ab09a94cda 100644
--- a/contrib/hstore_plperl/expected/hstore_plperl.out
+++ b/contrib/hstore_plperl/expected/hstore_plperl.out
@@ -41,6 +41,25 @@ SELECT test2arr();
{"\"a\"=>\"1\", \"b\"=>\"boo\", \"c\"=>NULL","\"d\"=>\"2\""}
(1 row)
+-- check error cases
+CREATE OR REPLACE FUNCTION test2() RETURNS hstore
+LANGUAGE plperl
+TRANSFORM FOR TYPE hstore
+AS $$
+return 42;
+$$;
+SELECT test2();
+ERROR: cannot transform non-hash Perl value to hstore
+CONTEXT: PL/Perl function "test2"
+CREATE OR REPLACE FUNCTION test2() RETURNS hstore
+LANGUAGE plperl
+TRANSFORM FOR TYPE hstore
+AS $$
+return [1, 2];
+$$;
+SELECT test2();
+ERROR: cannot transform non-hash Perl value to hstore
+CONTEXT: PL/Perl function "test2"
DROP FUNCTION test2();
DROP FUNCTION test2arr();
DROP EXTENSION hstore_plperl;
diff --git a/contrib/hstore_plperl/hstore_plperl.c b/contrib/hstore_plperl/hstore_plperl.c
index cc46a525f6f..0ce6743c1b8 100644
--- a/contrib/hstore_plperl/hstore_plperl.c
+++ b/contrib/hstore_plperl/hstore_plperl.c
@@ -101,7 +101,8 @@ Datum
plperl_to_hstore(PG_FUNCTION_ARGS)
{
dTHX;
- HV *hv = (HV *) SvRV((SV *) PG_GETARG_POINTER(0));
+ SV *in = (SV *) PG_GETARG_POINTER(0);
+ HV *hv;
HE *he;
int32 buflen;
int32 i;
@@ -109,6 +110,17 @@ plperl_to_hstore(PG_FUNCTION_ARGS)
HStore *out;
Pairs *pairs;
+ /* Dereference references recursively. */
+ while (SvROK(in))
+ in = SvRV(in);
+
+ /* Now we must have a hash. */
+ if (SvTYPE(in) != SVt_PVHV)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ (errmsg("cannot transform non-hash Perl value to hstore"))));
+ hv = (HV *) in;
+
pcount = hv_iterinit(hv);
pairs = palloc(pcount * sizeof(Pairs));
diff --git a/contrib/hstore_plperl/sql/hstore_plperl.sql b/contrib/hstore_plperl/sql/hstore_plperl.sql
index 9398aedfbbd..ad1db7eae17 100644
--- a/contrib/hstore_plperl/sql/hstore_plperl.sql
+++ b/contrib/hstore_plperl/sql/hstore_plperl.sql
@@ -31,6 +31,25 @@ $$;
SELECT test2arr();
+-- check error cases
+CREATE OR REPLACE FUNCTION test2() RETURNS hstore
+LANGUAGE plperl
+TRANSFORM FOR TYPE hstore
+AS $$
+return 42;
+$$;
+
+SELECT test2();
+
+CREATE OR REPLACE FUNCTION test2() RETURNS hstore
+LANGUAGE plperl
+TRANSFORM FOR TYPE hstore
+AS $$
+return [1, 2];
+$$;
+
+SELECT test2();
+
DROP FUNCTION test2();
DROP FUNCTION test2arr();