aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-06-04 18:02:13 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-06-04 18:02:13 -0400
commit30487423c8296ea448f4deb56f5caec46111b763 (patch)
tree74298bfc266aed02bb7856a2931541135f53c442 /src
parent09d7caad32d8d6987964a85ff71d12f18f63f43f (diff)
downloadpostgresql-30487423c8296ea448f4deb56f5caec46111b763.tar.gz
postgresql-30487423c8296ea448f4deb56f5caec46111b763.zip
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')
-rw-r--r--src/pl/tcl/expected/pltcl_call.out8
-rw-r--r--src/pl/tcl/pltcl.c11
-rw-r--r--src/pl/tcl/sql/pltcl_call.sql11
3 files changed, 28 insertions, 2 deletions
diff --git a/src/pl/tcl/expected/pltcl_call.out b/src/pl/tcl/expected/pltcl_call.out
index d290c8fbd05..d8c99b71b99 100644
--- a/src/pl/tcl/expected/pltcl_call.out
+++ b/src/pl/tcl/expected/pltcl_call.out
@@ -49,6 +49,14 @@ CALL test_proc6(2, 3, 4);
6 | 8
(1 row)
+-- syntax error in result tuple
+CREATE PROCEDURE test_proc10(INOUT a text)
+LANGUAGE pltcl
+AS $$
+return [list a {$a + $a}])
+$$;
+CALL test_proc10('abc');
+ERROR: could not parse function return value: list element in braces followed by ")" instead of space
DROP PROCEDURE test_proc1;
DROP PROCEDURE test_proc2;
DROP PROCEDURE test_proc3;
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 58fd3488706..4a41ea40407 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1029,7 +1029,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);
@@ -1296,7 +1299,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 */
@@ -1358,6 +1361,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)
diff --git a/src/pl/tcl/sql/pltcl_call.sql b/src/pl/tcl/sql/pltcl_call.sql
index 95791d08bee..804a23fb2da 100644
--- a/src/pl/tcl/sql/pltcl_call.sql
+++ b/src/pl/tcl/sql/pltcl_call.sql
@@ -52,6 +52,17 @@ $$;
CALL test_proc6(2, 3, 4);
+-- syntax error in result tuple
+
+CREATE PROCEDURE test_proc10(INOUT a text)
+LANGUAGE pltcl
+AS $$
+return [list a {$a + $a}])
+$$;
+
+CALL test_proc10('abc');
+
+
DROP PROCEDURE test_proc1;
DROP PROCEDURE test_proc2;
DROP PROCEDURE test_proc3;