Skip to content

Commit b631d01

Browse files
committed
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 26abb50 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
1 parent cd2624f commit b631d01

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

src/pl/tcl/expected/pltcl_call.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ END
6666
$$;
6767
NOTICE: a: 10
6868
NOTICE: _a: 10, _b: 20
69+
-- syntax error in result tuple
70+
CREATE PROCEDURE test_proc10(INOUT a text)
71+
LANGUAGE pltcl
72+
AS $$
73+
return [list a {$a + $a}])
74+
$$;
75+
CALL test_proc10('abc');
76+
ERROR: could not parse function return value: list element in braces followed by ")" instead of space
6977
DROP PROCEDURE test_proc1;
7078
DROP PROCEDURE test_proc2;
7179
DROP PROCEDURE test_proc3;

src/pl/tcl/pltcl.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,7 +1026,10 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
10261026
/* Convert function result to tuple */
10271027
resultObj = Tcl_GetObjResult(interp);
10281028
if (Tcl_ListObjGetElements(interp, resultObj, &resultObjc, &resultObjv) == TCL_ERROR)
1029-
throw_tcl_error(interp, prodesc->user_proname);
1029+
ereport(ERROR,
1030+
(errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
1031+
errmsg("could not parse function return value: %s",
1032+
utf_u2e(Tcl_GetStringResult(interp)))));
10301033

10311034
tup = pltcl_build_tuple_result(interp, resultObjv, resultObjc,
10321035
call_state);
@@ -1292,7 +1295,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
12921295
&result_Objc, &result_Objv) != TCL_OK)
12931296
ereport(ERROR,
12941297
(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1295-
errmsg("could not split return value from trigger: %s",
1298+
errmsg("could not parse trigger return value: %s",
12961299
utf_u2e(Tcl_GetStringResult(interp)))));
12971300

12981301
/* Convert function result to tuple */
@@ -1355,6 +1358,10 @@ pltcl_event_trigger_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
13551358

13561359
/**********************************************************************
13571360
* throw_tcl_error - ereport an error returned from the Tcl interpreter
1361+
*
1362+
* Caution: use this only to report errors returned by Tcl_EvalObjEx() or
1363+
* other variants of Tcl_Eval(). Other functions may not fill "errorInfo",
1364+
* so it could be unset or even contain details from some previous error.
13581365
**********************************************************************/
13591366
static void
13601367
throw_tcl_error(Tcl_Interp *interp, const char *proname)

src/pl/tcl/sql/pltcl_call.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ END
7171
$$;
7272

7373

74+
-- syntax error in result tuple
75+
76+
CREATE PROCEDURE test_proc10(INOUT a text)
77+
LANGUAGE pltcl
78+
AS $$
79+
return [list a {$a + $a}])
80+
$$;
81+
82+
CALL test_proc10('abc');
83+
84+
7485
DROP PROCEDURE test_proc1;
7586
DROP PROCEDURE test_proc2;
7687
DROP PROCEDURE test_proc3;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy