]> granicus.if.org Git - postgresql/commitdiff
Tighten coding for non-composite case in plperl's return_next.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 31 Jul 2017 15:33:46 +0000 (11:33 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 31 Jul 2017 15:33:46 +0000 (11:33 -0400)
Coverity complained about this code's practice of using scalar variables
as single-element arrays.  While that's really just nitpicking, it probably
is more readable to declare them as arrays, so let's do that.  A more
important point is that the code was just blithely assuming that the
result tupledesc has exactly one column; if it doesn't, we'd likely get
a crash of some sort in tuplestore_putvalues.  Since the tupledesc is
manufactured outside of plperl, that seems like an uncomfortably long
chain of assumptions.  We can nail it down at little cost with a sanity
check earlier in the function.

src/pl/plperl/plperl.c

index b10b4434aa74033d7858dc76ad6da4d6c77035d5..afebec910d6cb71ed1629457e63384901548faac 100644 (file)
@@ -3247,12 +3247,18 @@ plperl_return_next_internal(SV *sv)
 
                /*
                 * This is the first call to return_next in the current PL/Perl
-                * function call, so memoize some lookups
+                * function call, so identify the output tuple descriptor and create a
+                * tuplestore to hold the result rows.
                 */
                if (prodesc->fn_retistuple)
                        (void) get_call_result_type(fcinfo, NULL, &tupdesc);
                else
+               {
                        tupdesc = rsi->expectedDesc;
+                       /* Protect assumption below that we return exactly one column */
+                       if (tupdesc == NULL || tupdesc->natts != 1)
+                               elog(ERROR, "expected single-column result descriptor for non-composite SETOF result");
+               }
 
                /*
                 * Make sure the tuple_store and ret_tdesc are sufficiently
@@ -3300,20 +3306,20 @@ plperl_return_next_internal(SV *sv)
        }
        else
        {
-               Datum           ret;
-               bool            isNull;
+               Datum           ret[1];
+               bool            isNull[1];
 
-               ret = plperl_sv_to_datum(sv,
-                                                                prodesc->result_oid,
-                                                                -1,
-                                                                fcinfo,
-                                                                &prodesc->result_in_func,
-                                                                prodesc->result_typioparam,
-                                                                &isNull);
+               ret[0] = plperl_sv_to_datum(sv,
+                                                                       prodesc->result_oid,
+                                                                       -1,
+                                                                       fcinfo,
+                                                                       &prodesc->result_in_func,
+                                                                       prodesc->result_typioparam,
+                                                                       &isNull[0]);
 
                tuplestore_putvalues(current_call_data->tuple_store,
                                                         current_call_data->ret_tdesc,
-                                                        &ret, &isNull);
+                                                        ret, isNull);
        }
 
        MemoryContextSwitchTo(old_cxt);