diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2024-06-04 18:02:13 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2024-06-04 18:02:13 -0400 |
commit | dda633a039ee5f147e6315a786d7a162e898dc72 (patch) | |
tree | 530eaea734434101589a9b00b5f6296c536a3479 /src/pl/tcl/pltcl.c | |
parent | 1d5c5ae8e5557cfb974c290693802d8ebece25ac (diff) |
Fix pl/tcl's handling of errors from Tcl_ListObjGetElements().
In a procedure or function returning tuple, we use that function to
parse the Tcl script's result, which is supposed to be a Tcl list.
If it isn't, you get an error. Commit 26abb50c4 incautiously
supposed that we could use throw_tcl_error() to report such an error.
That doesn't actually work, because low-level functions like
Tcl_ListObjGetElements() don't fill Tcl's errorInfo variable.
The result is either a null-pointer-dereference crash or emission
of misleading context information describing the previous Tcl error.
Back off to just reporting the interpreter's result string, and
improve throw_tcl_error()'s comment to explain when to use it.
Also, although the similar code in pltcl_trigger_handler() avoided
this mistake, it was using a fairly confusing wording of the
error message. Improve that while we're here.
Per report from A. Kozhemyakin. Back-patch to all supported
branches.
Erik Wienhold and Tom Lane
Discussion: https://postgr.es/m/6a2a1c40-2b2c-4a33-8b72-243c0766fcda@postgrespro.ru
Diffstat (limited to 'src/pl/tcl/pltcl.c')
-rw-r--r-- | src/pl/tcl/pltcl.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c index 0aee719b267..82526552c52 100644 --- a/src/pl/tcl/pltcl.c +++ b/src/pl/tcl/pltcl.c @@ -1022,7 +1022,10 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, /* Convert function result to tuple */ resultObj = Tcl_GetObjResult(interp); if (Tcl_ListObjGetElements(interp, resultObj, &resultObjc, &resultObjv) == TCL_ERROR) - throw_tcl_error(interp, prodesc->user_proname); + ereport(ERROR, + (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), + errmsg("could not parse function return value: %s", + utf_u2e(Tcl_GetStringResult(interp))))); tup = pltcl_build_tuple_result(interp, resultObjv, resultObjc, call_state); @@ -1289,7 +1292,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, &result_Objc, &result_Objv) != TCL_OK) ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), - errmsg("could not split return value from trigger: %s", + errmsg("could not parse trigger return value: %s", utf_u2e(Tcl_GetStringResult(interp))))); /* Convert function result to tuple */ @@ -1352,6 +1355,10 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state, /********************************************************************** * throw_tcl_error - ereport an error returned from the Tcl interpreter + * + * Caution: use this only to report errors returned by Tcl_EvalObjEx() or + * other variants of Tcl_Eval(). Other functions may not fill "errorInfo", + * so it could be unset or even contain details from some previous error. **********************************************************************/ static void throw_tcl_error(Tcl_Interp *interp, const char *proname) |