Fix contrib/hstore_plperl to look through scalar refs.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 19:55:06 +0000 (15:55 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Jun 2018 19:55:06 +0000 (15:55 -0400)
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

contrib/hstore_plperl/expected/hstore_plperl.out
contrib/hstore_plperl/hstore_plperl.c
contrib/hstore_plperl/sql/hstore_plperl.sql

index 25fc506c23f035b2e11f4f97d606617bd4cd968f..1ab09a94cda472fedc64044c9dcac3aca9452b99 100644 (file)
@@ -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;
index e5303b3b92a59335f833d4d76867eef6bafbf100..7983426f49baa7e4e71d5f653f3e3f7a23031740 100644 (file)
@@ -47,7 +47,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;
@@ -55,6 +56,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));
index 9398aedfbbd5cd0178056c67bbf34546f1572f8e..ad1db7eae1799d1a7d1720d66b2c1c7da9e5df91 100644 (file)
@@ -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();