Skip to content

Commit a2dafc6

Browse files
committed
Fix bugs in pltcl's new return_null command: it was liable to go belly up
if the return datatype's input converter was at all strict, because the converter would get called on junk data when returning NULL. Also ensure that it gives an error rather than coredumping if someone tries to use it in a trigger function.
1 parent 60d1d67 commit a2dafc6

File tree

1 file changed

+41
-20
lines changed

1 file changed

+41
-20
lines changed

src/pl/tcl/pltcl.c

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* ENHANCEMENTS, OR MODIFICATIONS.
3232
*
3333
* IDENTIFICATION
34-
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.31 2000/12/08 00:09:07 tgl Exp $
34+
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.32 2001/02/16 03:26:40 tgl Exp $
3535
*
3636
**********************************************************************/
3737

@@ -103,7 +103,7 @@ static Tcl_Interp *pltcl_safe_interp = NULL;
103103
static Tcl_HashTable *pltcl_proc_hash = NULL;
104104
static Tcl_HashTable *pltcl_norm_query_hash = NULL;
105105
static Tcl_HashTable *pltcl_safe_query_hash = NULL;
106-
static FunctionCallInfo pltcl_actual_fcinfo = NULL;
106+
static FunctionCallInfo pltcl_current_fcinfo = NULL;
107107

108108
/**********************************************************************
109109
* Forward declarations
@@ -354,18 +354,18 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
354354
* Determine if called as function or trigger and
355355
* call appropriate subhandler
356356
************************************************************/
357-
save_fcinfo = pltcl_actual_fcinfo;
357+
save_fcinfo = pltcl_current_fcinfo;
358358

359359
if (CALLED_AS_TRIGGER(fcinfo))
360360
{
361-
pltcl_actual_fcinfo = NULL;
361+
pltcl_current_fcinfo = NULL;
362362
retval = PointerGetDatum(pltcl_trigger_handler(fcinfo));
363363
} else {
364-
pltcl_actual_fcinfo = fcinfo;
364+
pltcl_current_fcinfo = fcinfo;
365365
retval = pltcl_func_handler(fcinfo);
366366
}
367367

368-
pltcl_actual_fcinfo = save_fcinfo;
368+
pltcl_current_fcinfo = save_fcinfo;
369369

370370
pltcl_call_level--;
371371

@@ -743,17 +743,27 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
743743
* Disconnect from SPI manager and then create the return
744744
* values datum (if the input function does a palloc for it
745745
* this must not be allocated in the SPI memory context
746-
* because SPI_finish would free it).
746+
* because SPI_finish would free it). But don't try to call
747+
* the result_in_func if we've been told to return a NULL;
748+
* the contents of interp->result may not be a valid value of
749+
* the result type in that case.
747750
************************************************************/
748751
if (SPI_finish() != SPI_OK_FINISH)
749752
elog(ERROR, "pltcl: SPI_finish() failed");
750753

751-
retval = FunctionCall3(&prodesc->result_in_func,
752-
PointerGetDatum(interp->result),
753-
ObjectIdGetDatum(prodesc->result_in_elem),
754-
Int32GetDatum(-1));
754+
if (fcinfo->isnull)
755+
retval = (Datum) 0;
756+
else
757+
retval = FunctionCall3(&prodesc->result_in_func,
758+
PointerGetDatum(interp->result),
759+
ObjectIdGetDatum(prodesc->result_in_elem),
760+
Int32GetDatum(-1));
755761

762+
/************************************************************
763+
* Finally we may restore normal error handling.
764+
************************************************************/
756765
memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
766+
757767
return retval;
758768
}
759769

@@ -1345,7 +1355,7 @@ pltcl_argisnull(ClientData cdata, Tcl_Interp *interp,
13451355
int argc, char *argv[])
13461356
{
13471357
int argno;
1348-
FunctionCallInfo fcinfo = pltcl_actual_fcinfo;
1358+
FunctionCallInfo fcinfo = pltcl_current_fcinfo;
13491359

13501360
/************************************************************
13511361
* Check call syntax
@@ -1356,22 +1366,22 @@ pltcl_argisnull(ClientData cdata, Tcl_Interp *interp,
13561366
return TCL_ERROR;
13571367
}
13581368

1359-
/************************************************************
1360-
* Get the argument number
1361-
************************************************************/
1362-
if (Tcl_GetInt(interp, argv[1], &argno) != TCL_OK)
1363-
return TCL_ERROR;
1364-
13651369
/************************************************************
13661370
* Check that we're called as a normal function
13671371
************************************************************/
13681372
if (fcinfo == NULL)
13691373
{
13701374
Tcl_SetResult(interp, "argisnull cannot be used in triggers",
1371-
TCL_VOLATILE);
1375+
TCL_VOLATILE);
13721376
return TCL_ERROR;
13731377
}
13741378

1379+
/************************************************************
1380+
* Get the argument number
1381+
************************************************************/
1382+
if (Tcl_GetInt(interp, argv[1], &argno) != TCL_OK)
1383+
return TCL_ERROR;
1384+
13751385
/************************************************************
13761386
* Check that the argno is valid
13771387
************************************************************/
@@ -1402,7 +1412,7 @@ pltcl_returnnull(ClientData cdata, Tcl_Interp *interp,
14021412
int argc, char *argv[])
14031413
{
14041414
int argno;
1405-
FunctionCallInfo fcinfo = pltcl_actual_fcinfo;
1415+
FunctionCallInfo fcinfo = pltcl_current_fcinfo;
14061416

14071417
/************************************************************
14081418
* Check call syntax
@@ -1413,11 +1423,22 @@ pltcl_returnnull(ClientData cdata, Tcl_Interp *interp,
14131423
return TCL_ERROR;
14141424
}
14151425

1426+
/************************************************************
1427+
* Check that we're called as a normal function
1428+
************************************************************/
1429+
if (fcinfo == NULL)
1430+
{
1431+
Tcl_SetResult(interp, "return_null cannot be used in triggers",
1432+
TCL_VOLATILE);
1433+
return TCL_ERROR;
1434+
}
1435+
14161436
/************************************************************
14171437
* Set the NULL return flag and cause Tcl to return from the
14181438
* procedure.
14191439
************************************************************/
14201440
fcinfo->isnull = true;
1441+
14211442
return TCL_RETURN;
14221443
}
14231444

0 commit comments

Comments
 (0)