]> granicus.if.org Git - postgresql/commitdiff
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 6bc3bb37fc3ba356fb4b012512c690f971454f90..c09bd38d090e89863140ef0f8910cc2d90712094 100644 (file)
@@ -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));
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();